Skip to content

Commit 49607cc

Browse files
Provide tools to build unchained language standalones
Add `mx_sdk_vm_ng` with a number of helper project, build tasks, and distributions that can be used to build "unchained" language standalone. In particular they allow building native images using a bootstrap GraalVM (or the current stage1) without requiring the input jars and build arguments to be part of a legacy stage1 GraalVM. * `NativeImageLibraryProject` allows defining shared libraries built with native-image: ``` "mylib": { "class": "NativeImageLibraryProject", "dependencies": ["SOME_JAR"], "build_args": ["-R:+InstallSegfaultHandler"], }, ``` There is also the `LanguageLibraryProject` subclass that has good defaults for truffle languages. By default, if the `substratevm` suite is loaded, it will use native-image from the current legacy stage1 GraalVM. If `substartevm` is not loaded, those native image projects will be ignored and liklely cause layout distributions that contain them to be recursively ignored. If the `BOOTSTRAP_GRAALVM` environment variable is set, it will be used to build those native images instead. If this is not set but `JAVA_HOME` contains the native-image tools, it will be used. These projects are build by default and respect `mx --native-images=...` arguments. * `NativeImageExecutableProject` is similar but is used to build executables instead of shared library. * `ThinLauncherProject` allows building a thin native launcher that can be used to start a JVM or a native language library: ``` "mylauncher": { "class": "ThinLauncherProject", "mainClass": "org.example.MyLauncher", "jar_distributions": ["MY_LAUNCHER"], "relative_jre_path": "../jvm", # for JVM mode "relative_module_path": "../modules", # for JVM mode }, ``` * `StandaloneLicenses` can be used to provide licenses that can be used in a layout distribution. It adapts to the current context being "community" or "enterprise": ``` "truffleruby_licenses": { "class": "StandaloneLicenses", "community_license_file": "LICENCE.md", "community_3rd_party_license_file": "3rd_party_licenses.txt", }, ``` * `JavaHomeDependency` can be used to represent a java home in the mx build system. It can be used in layout distributions to copy a JDK. * `DynamicPOMDistribution` is like mx's `POMDistribution` but additionally supports `dynamicDistDependencies` and `dynamicDistDependencies` attributes which call back into the suite's mx extensions to dynamically retrieve a list of distributions. This can replace the use of `mx_register_dynamic_suite_constituents`. ```python filename="suite.py" "MY_DISTRIBUTION": { "class": "DynamicPOMDistribution", "distDependencies": ["A_STATIC_DEPENDENCY"], "dynamicDistDependencies": "my_callback", }, ``` ```python filename="mx_mysuite.py" def my_callback(): return [] if foo else ['A_DYNAMIC_DEPENDENCY'] ``` * `DeliverableStandaloneArchive` can be used to make an archive for a standalone based on a layout "dir" distribution. It will adjust its name based on the current context being "community" or "enterprise". It ensure that the archive has a single root directory for easy consumption by user (multiple `tar xf ...` in the same directory will not conflit). * `sdk:STANDALONE_JAVA_HOME` is a dependency that can be used in a layout distribution to get a JDK that can be used in a standalone. The `STANDALONE_JAVA_HOME` environment variable can be used to point at an explicit JDK. Otherwise it will be the `BOOTSTRAP_GRAALVM` if it is set. If `BOOTSTRAP_GRAALVM` was not set but `JAVA_HOME` contains the native-image tool, `JAVA_HOME` is used. If none of the above works, it will be similar to the JDK that used to be inserted into legacy standalones: a special jlink'd JDK that contains the sdk and libgraal if it is available. * `sdk:TOOLS_FOR_STANDALONE` is a convenience pom distribution that can be used to depend on all known tools if they are available. * `ExtractedEngineResources` can be used to obtain the engine resources for use in a layout distributions. ``` "my-resources": { "class": "ExtractedEngineResources", "dependencies": ['LANG_AND_RESOURCES_DISTS'], }, ... "layout": { "resources/": "dependency:my-resources/mylang/*", }, ``` Note that native image projects also produce copied internal resources if `-H:+CopyLanguageResources` is used. * Define TRUFFLE_ATTACH_GRAALVM_SUPPORT to be used for standalones: ``` "jvmlibs/": [ "extracted-dependency:truffle:TRUFFLE_ATTACH_GRAALVM_SUPPORT", "extracted-dependency:truffle:TRUFFLE_NFI_NATIVE_GRAALVM_SUPPORT", ], ``` Co-authored-by: Benoit Daloze <[email protected]>
1 parent 3e4fd56 commit 49607cc

File tree

9 files changed

+1136
-92
lines changed

9 files changed

+1136
-92
lines changed

common.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"Jsonnet files should not include this file directly but use ci/common.jsonnet instead."
55
],
66

7-
"mx_version": "7.40.2",
7+
"mx_version": "7.45.0",
88

99
"COMMENT.jdks": "When adding or removing JDKs keep in sync with JDKs in ci/common.jsonnet",
1010
"jdks": {

espresso/mx.espresso/mx_espresso.py

+2-44
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,10 @@
3838
import mx_espresso_benchmarks # pylint: disable=unused-import
3939
import mx_sdk_vm
4040
import mx_sdk_vm_impl
41+
from mx_sdk_vm_ng import JavaHomeDependency
4142
from mx_gate import Task, add_gate_runner
4243
from mx_jackpot import jackpot
43-
from os.path import join, isabs, exists, dirname, relpath, basename
44+
from os.path import join, exists, dirname, relpath
4445
from import_order import verify_order, validate_format
4546

4647
_suite = mx.suite('espresso')
@@ -587,49 +588,6 @@ def register_espresso_runtime_resources(register_project, register_distribution,
587588
}))
588589

589590

590-
class JavaHomeDependency(mx.BaseLibrary):
591-
def __init__(self, suite, name, java_home):
592-
assert isabs(java_home)
593-
self.java_home = java_home
594-
release_dict = mx_sdk_vm.parse_release_file(join(java_home, 'release'))
595-
self.is_ee_implementor = release_dict.get('IMPLEMENTOR') == 'Oracle Corporation'
596-
self.version = mx.VersionSpec(release_dict.get('JAVA_VERSION'))
597-
self.major_version = self.version.parts[1] if self.version.parts[0] == 1 else self.version.parts[0]
598-
if self.is_ee_implementor:
599-
the_license = "Oracle Proprietary"
600-
else:
601-
the_license = "GPLv2-CPE"
602-
super().__init__(suite, name, optional=False, theLicense=the_license)
603-
self.deps = []
604-
605-
def is_available(self):
606-
return True
607-
608-
def getBuildTask(self, args):
609-
return mx.ArchivableBuildTask(self, args, 1)
610-
611-
def getResults(self):
612-
for root, _, files in os.walk(self.java_home):
613-
for name in files:
614-
yield join(root, name)
615-
616-
def getArchivableResults(self, use_relpath=True, single=False):
617-
if single:
618-
raise ValueError("single not supported")
619-
for path in self.getResults():
620-
if use_relpath:
621-
arcname = relpath(path, self.java_home)
622-
else:
623-
arcname = basename(path)
624-
yield path, arcname
625-
626-
def post_init(self):
627-
pass # help act like a distribution since this is registered as a distribution
628-
629-
def archived_deps(self):
630-
return [] # help act like a distribution since this is registered as a distribution
631-
632-
633591
class EspressoRuntimeResourceProject(mx.JavaProject):
634592
def __init__(self, suite, subDir, runtime_name, theLicense):
635593
name = f'com.oracle.truffle.espresso.resources.runtime'

sdk/mx.sdk/mx_sdk.py

+2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import mx_gate
4747
import mx_sdk_vm
4848
import mx_sdk_vm_impl
49+
import mx_sdk_vm_ng
4950
import pathlib
5051
import mx_sdk_benchmark # pylint: disable=unused-import
5152
import mx_sdk_clangformat # pylint: disable=unused-import
@@ -193,6 +194,7 @@ def upx(args):
193194

194195
def mx_register_dynamic_suite_constituents(register_project, register_distribution):
195196
mx_sdk_vm_impl.mx_register_dynamic_suite_constituents(register_project, register_distribution)
197+
mx_sdk_vm_ng.mx_register_dynamic_suite_constituents(register_project, register_distribution)
196198

197199

198200
def mx_post_parse_cmd_line(args):

sdk/mx.sdk/mx_sdk_vm_impl.py

+43-34
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@
6060
import textwrap
6161
import zipfile
6262

63+
import mx_sdk_vm_ng
64+
6365
try:
6466
# Use more secure defusedxml library, if available
6567
from defusedxml.ElementTree import parse as etreeParse
@@ -3154,7 +3156,7 @@ def get_stage1_graalvm_distribution():
31543156
""":rtype: GraalVmLayoutDistribution"""
31553157
global _stage1_graalvm_distribution
31563158
if _stage1_graalvm_distribution == 'uninitialized':
3157-
_stage1_graalvm_distribution = GraalVmLayoutDistribution(_graalvm_base_name, stage1=True)
3159+
_stage1_graalvm_distribution = GraalVmLayoutDistribution(_graalvm_base_name, stage1=True, defaultBuild=False)
31583160
_stage1_graalvm_distribution.description = "GraalVM distribution (stage1)"
31593161
_stage1_graalvm_distribution.maven = False
31603162
return _stage1_graalvm_distribution
@@ -3517,10 +3519,10 @@ def register_main_dist(dist, label):
35173519
register_distribution(debuginfo_dist)
35183520
main_dists[label].append(debuginfo_dist.name)
35193521

3520-
_final_graalvm_distribution = get_final_graalvm_distribution()
3522+
final_graalvm_distribution = get_final_graalvm_distribution()
35213523

35223524
from mx_native import TargetSelection
3523-
for c in _final_graalvm_distribution.components:
3525+
for c in final_graalvm_distribution.components:
35243526
if c.extra_native_targets:
35253527
for t in c.extra_native_targets:
35263528
mx.logv(f"Selecting extra target '{t}' from GraalVM component '{c.short_name}'.")
@@ -3532,7 +3534,7 @@ def register_main_dist(dist, label):
35323534

35333535
names = set()
35343536
short_names = set()
3535-
needs_stage1 = False
3537+
needs_stage1 = mx_sdk_vm_ng.requires_native_image_stage1()
35363538
installables = {}
35373539
jvmci_parent_jars = []
35383540
modified_jmods = {}
@@ -3600,10 +3602,10 @@ def register_main_dist(dist, label):
36003602
register_project(native_image_resources_filelist_project)
36013603

36023604
# Register main distribution
3603-
register_main_dist(_final_graalvm_distribution, 'graalvm')
3605+
register_main_dist(final_graalvm_distribution, 'graalvm')
36043606

36053607
# Register standalones
3606-
needs_java_standalone_jimage = False
3608+
needs_java_standalone_jimage = mx_sdk_vm_ng.requires_standalone_jimage()
36073609
for components in installables.values():
36083610
main_component = _get_main_component(components)
36093611
svm_support = _get_svm_support()
@@ -3622,7 +3624,7 @@ def register_main_dist(dist, label):
36223624
mx.warn("Skipping JVM standalone of '{}' because it contains launcher configs that are not yet supported".format(main_component.name))
36233625
else:
36243626
needs_java_standalone_jimage = True
3625-
java_standalone = GraalVmStandaloneComponent(get_component(main_component.name, fatalIfMissing=True), _final_graalvm_distribution, is_jvm=True, defaultBuild=False)
3627+
java_standalone = GraalVmStandaloneComponent(get_component(main_component.name, fatalIfMissing=True), final_graalvm_distribution, is_jvm=True, defaultBuild=False)
36263628
register_main_dist(java_standalone, 'graalvm_standalones')
36273629

36283630
# Use `main_component.library_configs` rather than `_get_library_configs(main_component)` because we
@@ -3638,7 +3640,7 @@ def register_main_dist(dist, label):
36383640
only_native_launchers = not main_component.launcher_configs or has_svm_launcher(main_component)
36393641
only_native_libraries = not main_component.library_configs or (svm_support.is_supported() and not _has_skipped_libraries(main_component))
36403642
if only_native_launchers and only_native_libraries:
3641-
native_standalone = GraalVmStandaloneComponent(get_component(main_component.name, fatalIfMissing=True), _final_graalvm_distribution, is_jvm=False, defaultBuild=False)
3643+
native_standalone = GraalVmStandaloneComponent(get_component(main_component.name, fatalIfMissing=True), final_graalvm_distribution, is_jvm=False, defaultBuild=False)
36423644
register_main_dist(native_standalone, 'graalvm_standalones')
36433645

36443646
if needs_java_standalone_jimage:
@@ -3661,7 +3663,7 @@ def register_main_dist(dist, label):
36613663
suite=_suite,
36623664
name='java-standalone-jimage',
36633665
jimage_jars=sorted(java_standalone_jimage_jars),
3664-
jimage_ignore_jars=sorted(_final_graalvm_distribution.jimage_ignore_jars),
3666+
jimage_ignore_jars=sorted(final_graalvm_distribution.jimage_ignore_jars),
36653667
workingSets=None,
36663668
defaultBuild=False,
36673669
missing_export_target_action='warn',
@@ -3677,32 +3679,34 @@ def register_main_dist(dist, label):
36773679
else:
36783680
config_class = GraalVmMiscLauncher
36793681
for launcher_config in _get_launcher_configs(component):
3680-
register_project(config_class(component, launcher_config, stage1=True))
3681-
for component in registered_graalvm_components(stage1=False):
3682-
# native properties in the final distribution also need native properties in the stage1 distribution
3683-
for launcher_config in _get_launcher_configs(component):
3684-
register_project(GraalVmNativeProperties(component, launcher_config, stage1=True))
3685-
for library_config in _get_library_configs(component):
3686-
register_project(GraalVmNativeProperties(component, library_config, stage1=True))
3682+
register_project(config_class(component, launcher_config, stage1=True, defaultBuild=False))
3683+
if get_component('svm', stage1=True):
3684+
for component in registered_graalvm_components(stage1=False):
3685+
# native properties in the final distribution also need native properties in the stage1 distribution
3686+
for launcher_config in _get_launcher_configs(component):
3687+
register_project(GraalVmNativeProperties(component, launcher_config, stage1=True, defaultBuild=False))
3688+
for library_config in _get_library_configs(component):
3689+
register_project(GraalVmNativeProperties(component, library_config, stage1=True, defaultBuild=False))
36873690
register_distribution(get_stage1_graalvm_distribution())
36883691

36893692
if register_project:
36903693
if needs_stage1:
3691-
_stage1_graalvm_distribution = get_stage1_graalvm_distribution()
3692-
if _needs_stage1_jimage(_stage1_graalvm_distribution, _final_graalvm_distribution):
3694+
stage1_graalvm_distribution = get_stage1_graalvm_distribution()
3695+
if _needs_stage1_jimage(stage1_graalvm_distribution, final_graalvm_distribution):
36933696
register_project(GraalVmJImage(
36943697
suite=_suite,
36953698
name='graalvm-stage1-jimage',
3696-
jimage_jars=sorted(_stage1_graalvm_distribution.jimage_jars),
3697-
jimage_ignore_jars=sorted(_stage1_graalvm_distribution.jimage_ignore_jars),
3699+
jimage_jars=sorted(stage1_graalvm_distribution.jimage_jars),
3700+
jimage_ignore_jars=sorted(stage1_graalvm_distribution.jimage_ignore_jars),
36983701
workingSets=None,
36993702
default_to_jvmci=False, # decide depending on the included modules
3703+
defaultBuild=False,
37003704
))
37013705
final_jimage_project = GraalVmJImage(
37023706
suite=_suite,
37033707
name='graalvm-jimage',
3704-
jimage_jars=sorted(_final_graalvm_distribution.jimage_jars),
3705-
jimage_ignore_jars=sorted(_final_graalvm_distribution.jimage_ignore_jars),
3708+
jimage_jars=sorted(final_graalvm_distribution.jimage_jars),
3709+
jimage_ignore_jars=sorted(final_graalvm_distribution.jimage_ignore_jars),
37063710
workingSets=None,
37073711
default_to_jvmci=_get_libgraal_component() is not None,
37083712
)
@@ -4575,15 +4579,16 @@ def _expand_native_images_list(only):
45754579
return only
45764580

45774581

4578-
def _force_bash_launchers(launcher):
4582+
def _force_bash_launchers(launcher, build_by_default=None):
45794583
"""
45804584
:type launcher: str | mx_sdk.LauncherConfig
45814585
"""
45824586
launcher_name = _get_launcher_name(launcher)
45834587

45844588
forced = _parse_cmd_arg('force_bash_launchers')
4585-
default = has_vm_suite() or forced is not None # for compatibility with legacy behavior
4586-
only = _parse_cmd_arg('native_images', default_value=str(default))
4589+
if build_by_default is None:
4590+
build_by_default = has_vm_suite() or forced is not None # for compatibility with legacy behavior
4591+
only = _parse_cmd_arg('native_images', default_value=str(build_by_default))
45874592
only = _expand_native_images_list(only)
45884593
if isinstance(only, bool):
45894594
included = only
@@ -4598,15 +4603,16 @@ def _force_bash_launchers(launcher):
45984603
return not included
45994604

46004605

4601-
def _skip_libraries(library):
4606+
def _skip_libraries(library, build_by_default=None):
46024607
"""
46034608
:type library: str | mx_sdk.LibraryConfig
46044609
"""
46054610
library_name = _get_library_name(library)
46064611

46074612
skipped = _parse_cmd_arg('skip_libraries')
4608-
default = has_vm_suite() or skipped is not None # for compatibility with legacy behavior
4609-
only = _parse_cmd_arg('native_images', default_value=str(default))
4613+
if build_by_default is None:
4614+
build_by_default = has_vm_suite() or skipped is not None # for compatibility with legacy behavior
4615+
only = _parse_cmd_arg('native_images', default_value=str(build_by_default))
46104616
only = _expand_native_images_list(only)
46114617
if isinstance(only, bool):
46124618
included = only
@@ -4748,12 +4754,15 @@ def _generate_debuginfo(image_config):
47484754
elif isinstance(generate_debuginfo, bool):
47494755
return generate_debuginfo
47504756
else:
4751-
destination = image_config.destination if isinstance(image_config, mx_sdk.AbstractNativeImageConfig) else image_config
4752-
if isinstance(image_config, mx_sdk.LauncherConfig):
4753-
name = basename(remove_exe_suffix(destination, require_suffix=False))
4754-
elif isinstance(image_config, mx_sdk.LibraryConfig):
4755-
name = remove_lib_prefix_suffix(basename(destination), require_suffix_prefix=False)
4756-
generate_debuginfo = [lib[4:] for lib in generate_debuginfo if lib.startswith('lib:')]
4757+
if isinstance(image_config, str):
4758+
name = image_config
4759+
else:
4760+
destination = image_config.destination if isinstance(image_config, mx_sdk.AbstractNativeImageConfig) else image_config
4761+
if isinstance(image_config, mx_sdk.LauncherConfig):
4762+
name = basename(remove_exe_suffix(destination, require_suffix=False))
4763+
elif isinstance(image_config, mx_sdk.LibraryConfig):
4764+
name = remove_lib_prefix_suffix(basename(destination), require_suffix_prefix=False)
4765+
generate_debuginfo = [lib[4:] for lib in generate_debuginfo if lib.startswith('lib:')]
47574766
return name in generate_debuginfo
47584767

47594768

0 commit comments

Comments
 (0)