diff --git a/sdk/mx.sdk/mx_sdk_vm.py b/sdk/mx.sdk/mx_sdk_vm.py index 6117739003b0..1c0e288c37eb 100644 --- a/sdk/mx.sdk/mx_sdk_vm.py +++ b/sdk/mx.sdk/mx_sdk_vm.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2019, 2025, 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 @@ -263,7 +263,8 @@ def __init__(self, extra_installable_qualifiers=None, has_relative_home=True, jvm_configs=None, - extra_native_targets=None): + extra_native_targets=None, + final_stage_only=False): """ :param suite mx.Suite: the suite this component belongs to :type name: str @@ -281,6 +282,7 @@ def __init__(self, 'priority': -1, # 0 is invalid; < 0 prepends to the default configs; > 0 appends } :param extra_native_targets: list of str, enables extra targets in multi-target projects. + :param final_stage_only: bool, this component should be only included in the final GraalVM, not in stage1 :type license_files: list[str] :type third_party_license_files: list[str] :type polyglot_lib_build_args: list[str] @@ -305,6 +307,7 @@ def __init__(self, :type extra_installable_qualifiers: list[str] | None :type has_relative_home: bool :type jvm_configs: list[dict] or None + :type final_stage_only: bool """ if dependencies is None: mx.logv('Component {} does not specify dependencies'.format(name)) @@ -343,6 +346,7 @@ def __init__(self, self.has_relative_home = has_relative_home self.jvm_configs = jvm_configs or [] self.extra_native_targets = extra_native_targets + self.final_stage_only = final_stage_only if supported is not None or early_adopter: if stability is not None: diff --git a/sdk/mx.sdk/mx_sdk_vm_impl.py b/sdk/mx.sdk/mx_sdk_vm_impl.py index b889c71427b5..1a8da62bf1db 100644 --- a/sdk/mx.sdk/mx_sdk_vm_impl.py +++ b/sdk/mx.sdk/mx_sdk_vm_impl.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2019, 2025, 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 @@ -166,6 +166,8 @@ def add_dependencies(dependencies, excludes=True): components = dependencies[:] while components: component = components.pop(0) + if component.final_stage_only and stage1: + continue if component not in components_to_build and not (excludes and is_excluded(component)): components_to_build.append(component) components.extend(component.direct_dependencies()) @@ -495,11 +497,7 @@ def _add_link(_dest, _target, _component=None, _dest_base_name=None): if _linkname != dest_base_name: if mx.is_windows(): if _target.endswith('.exe') or _target.endswith('.cmd'): - link_template_name = join(_suite.mxDir, 'vm', 'exe_link_template.cmd') - with open(link_template_name, 'r') as template: - _template_subst = mx_subst.SubstitutionEngine(mx_subst.string_substitutions) - _template_subst.register_no_arg('target', normpath(_linkname)) - contents = _template_subst.substitute(template.read()) + contents = mx_sdk_vm_ng._make_windows_link(_linkname) full_dest = _dest + dest_base_name[:-len('.exe')] + '.cmd' _add(layout, full_dest, 'string:{}'.format(contents), _component) return full_dest @@ -2753,11 +2751,7 @@ def add_files_from_component(comp, path_prefix, excluded_paths): link_target = relpath(launcher_dest, start=dirname(link_dest)) if mx.is_windows(): if link_target.endswith('.exe') or link_target.endswith('.cmd'): - link_template_name = join(_suite.mxDir, 'vm', 'exe_link_template.cmd') - with open(link_template_name, 'r') as template: - _template_subst = mx_subst.SubstitutionEngine(mx_subst.string_substitutions) - _template_subst.register_no_arg('target', normpath(link_target)) - contents = _template_subst.substitute(template.read()) + contents = mx_sdk_vm_ng._make_windows_link(link_target) full_dest = link_dest[:-len('.exe')] + '.cmd' layout.setdefault(full_dest, []).append({ 'source_type': 'string', diff --git a/sdk/mx.sdk/mx_sdk_vm_ng.py b/sdk/mx.sdk/mx_sdk_vm_ng.py index 3698291e978a..a7f5d76f372f 100644 --- a/sdk/mx.sdk/mx_sdk_vm_ng.py +++ b/sdk/mx.sdk/mx_sdk_vm_ng.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2025, 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 @@ -44,7 +44,7 @@ import sys from abc import ABCMeta, abstractmethod from os import listdir, linesep -from os.path import join, exists, isfile, basename, relpath, isdir, isabs, dirname +from os.path import join, exists, isfile, basename, relpath, isdir, isabs, dirname, normpath from typing import Tuple import mx @@ -381,6 +381,9 @@ def __init__(self, args, project: NativeImageProject): max_parallelism = 12 super().__init__(project, args, min(max_parallelism, mx.cpu_count())) + def newestOutput(self): + return mx.TimeStampFile.newest([_path for _path, _ in self.subject.getArchivableResults()]) + def get_build_args(self): experimental_build_args = [ '-H:+GenerateBuildArtifactsFile', # generate 'build-artifacts.json' @@ -931,6 +934,49 @@ def witness_contents(self): return f"roots: {', '.join(self.subject.root_components)}\nignored: {', '.join(self.subject.ignore_components)}" +def _make_windows_link(link_target): + link_template_name = join(_suite.mxDir, 'vm', 'exe_link_template.cmd') + with open(link_template_name, 'r') as template: + _template_subst = mx_subst.SubstitutionEngine(mx_subst.string_substitutions) + _template_subst.register_no_arg('target', normpath(link_target)) + return _template_subst.substitute(template.read()) + + +class ToolchainToolDistribution(mx.LayoutDirDistribution): + def __init__(self, suite, name=None, deps=None, excludedLibs=None, platformDependent=True, theLicense=None, defaultBuild=True, **kw_args): + self.tool_project = _require(kw_args, 'tool_project', suite, name) + self.tool_links = _require(kw_args, 'tool_links', suite, name) + + layout = { + './': [{ + "source_type": "dependency", + "dependency": self.tool_project, + }] + } + + super().__init__(suite, name=name, deps=[], layout=layout, path=None, theLicense=theLicense, platformDependent=True, defaultBuild=defaultBuild) + + def resolveDeps(self): + self.tool_project = mx.project(self.tool_project) + _, main_tool_name = next(self.tool_project.getArchivableResults(single=True)) + + def _add_link(name, target): + if mx.is_windows(): + # ignore indirect symlinks on windows and link everything directly to the main tool + # otherwise we lose the original program name + self.layout[f'./{name}.cmd'] = f'string:{_make_windows_link(main_tool_name)}' + else: + self.layout[f'./{name}'] = f'link:{target}' + + for tool in self.tool_links: + _add_link(tool, main_tool_name) + alt_names = self.tool_links[tool] + for alt_name in alt_names: + _add_link(alt_name, tool) + + super().resolveDeps() + + if mx.is_windows(): DeliverableArchiveSuper = mx.LayoutZIPDistribution else: @@ -938,7 +984,7 @@ def witness_contents(self): class DeliverableStandaloneArchive(DeliverableArchiveSuper): - def __init__(self, suite, name=None, deps=None, excludedLibs=None, platformDependent=True, theLicense=None, **kw_args): + def __init__(self, suite, name=None, deps=None, excludedLibs=None, platformDependent=True, theLicense=None, defaultBuild=True, **kw_args): standalone_dir_dist = _require(kw_args, 'standalone_dist', suite, name) community_archive_name = _require(kw_args, 'community_archive_name', suite, name) enterprise_archive_name = _require(kw_args, 'enterprise_archive_name', suite, name) @@ -959,11 +1005,16 @@ def __init__(self, suite, name=None, deps=None, excludedLibs=None, platformDepen dist_name = 'STANDALONE_' + community_archive_name.upper().replace('-', '_') layout = { - f'{dir_name}/': f'dependency:{standalone_dir_dist}/*' + f'{dir_name}/': { + "source_type": "dependency", + "dependency": standalone_dir_dist, + "path": "*", + "dereference": "never", + } } self.standalone_dir_dist = standalone_dir_dist maven = { 'groupId': 'org.graalvm', 'tag': 'standalone' } - super().__init__(suite, name=dist_name, deps=[], layout=layout, path=None, theLicense=theLicense, platformDependent=True, path_substitutions=path_substitutions, string_substitutions=string_substitutions, maven=maven) + super().__init__(suite, name=dist_name, deps=[], layout=layout, path=None, theLicense=theLicense, platformDependent=True, path_substitutions=path_substitutions, string_substitutions=string_substitutions, maven=maven, defaultBuild=defaultBuild) self.buildDependencies.append(standalone_dir_dist) def resolveDeps(self): diff --git a/sulong/ci/ci.jsonnet b/sulong/ci/ci.jsonnet index 6b66bc7f7dfa..c422f030782f 100644 --- a/sulong/ci/ci.jsonnet +++ b/sulong/ci/ci.jsonnet @@ -39,6 +39,8 @@ local sc = (import "ci_common/sulong-common.jsonnet"); "/regex/**", "/java-benchmarks/**", ] + (if standalone then [ + # tools suite (included in standalone) + "/tools/**", # substratevm and its dependencies "/substratevm/**", # vm and its dependencies @@ -56,21 +58,21 @@ local sc = (import "ci_common/sulong-common.jsonnet"); run+: [ ["mx", "build", "--dependencies", "SULONG_TEST"], ["mx", "unittest", "--verbose", "-Dsulongtest.toolchainPathPattern=SULONG_BOOTSTRAP_TOOLCHAIN", "ToolchainAPITest"], - ["mx", "--env", "toolchain-only", "build"], - ["set-export", "SULONG_BOOTSTRAP_GRAALVM", ["mx", "--quiet", "--no-warning", "--env", "toolchain-only", "graalvm-home"]], - ["mx", "unittest", "--verbose", "-Dsulongtest.toolchainPathPattern=GRAALVM_TOOLCHAIN_ONLY", "ToolchainAPITest"], + ["mx", "--env", "ce-llvm-standalones", "build", "--dependencies", "SULONG_JVM_STANDALONE"], + ["set-export", "SULONG_BOOTSTRAP_STANDALONE", ["mx", "--quiet", "--no-warning", "--env", "ce-llvm-standalones", "path", "--output", "SULONG_JVM_STANDALONE"]], + ["mx", "unittest", "--verbose", "-Dsulongtest.toolchainPathPattern=SULONG_JVM_STANDALONE", "ToolchainAPITest"], ], }, regular_builds:: [ $.sulong + $.gate(style=true) + sc.labsjdkLatest + sc.linux_amd64 + sc.style + { name: "gate-sulong-style-fullbuild-jdk-latest-linux-amd64" }, - $.sulong + $.gate(standalone=true) + sc.labsjdkLatest + sc.linux_amd64 + sc.llvmBundled + sc.requireGMP + sc.requireGCC + sc.gateTags("build,sulongMisc,parser") + $.sulong_test_toolchain + { name: "gate-sulong-misc-parser-jdk-latest-linux-amd64" }, + $.sulong + $.gate(standalone=true) + sc.labsjdkLatest + sc.linux_amd64 + sc.llvmBundled + sc.requireGMP + sc.gateTags("build,sulongMisc,parser") + $.sulong_test_toolchain + { name: "gate-sulong-misc-parser-jdk-latest-linux-amd64" }, $.sulong + $.gate() + sc.labsjdkLatest + sc.linux_amd64 + sc.llvmBundled + sc.requireGMP + sc.gateTags("build,gcc_c") + { name: "gate-sulong-gcc_c-jdk-latest-linux-amd64", timelimit: "45:00" }, $.sulong + $.gate() + sc.labsjdkLatest + sc.linux_amd64 + sc.llvmBundled + sc.requireGMP + sc.gateTags("build,gcc_cpp") + { name: "gate-sulong-gcc_cpp-jdk-latest-linux-amd64", timelimit: "45:00" }, $.sulong + $.gate() + sc.labsjdkLatest + sc.darwin_amd64 + sc.llvmBundled + sc.gateTags(basicTags) + { name: "gate-sulong-basic-nwcc-llvm-jdk-latest-darwin-amd64", timelimit: "0:45:00", capabilities+: ["ram16gb"] }, - $.sulong + $.gate() + sc.labsjdkLatest + sc.linux_amd64 + sc.llvmBundled + sc.requireGMP + sc.requireGCC + sc.gateTags(basicTags) + { name: "gate-sulong-basic-nwcc-llvm-jdk-latest-linux-amd64" }, + $.sulong + $.gate() + sc.labsjdkLatest + sc.linux_amd64 + sc.llvmBundled + sc.requireGMP + sc.gateTags(basicTags) + { name: "gate-sulong-basic-nwcc-llvm-jdk-latest-linux-amd64" }, $.sulong + $.gate() + sc.labsjdkLatest + sc.linux_aarch64 + sc.llvmBundled + sc.requireGMP + sc.gateTags(basicTagsNoNWCC) + { name: "gate-sulong-basic-llvm-jdk-latest-linux-aarch64", timelimit: "30:00" }, diff --git a/sulong/ci/ci_common/sulong-common.jsonnet b/sulong/ci/ci_common/sulong-common.jsonnet index 0fecfc28b1b9..889883ccbc5c 100644 --- a/sulong/ci/ci_common/sulong-common.jsonnet +++ b/sulong/ci/ci_common/sulong-common.jsonnet @@ -158,7 +158,7 @@ local sulong_deps = common.deps.sulong; extra_gate_args+:: ["--strict-mode"], }, - coverage(builds):: $.llvmBundled + $.requireGMP + $.optionalGCC + $.mxGate + { + coverage(builds):: $.llvmBundled + $.requireGMP + $.mxGate + { local sameArchBuilds = std.filter(function(b) b.os == self.os && b.arch == self.arch, builds), local allTags = std.set(std.flattenArrays([b.gateTags for b in sameArchBuilds if std.objectHasAll(b, "gateTags")])), local coverageTags = std.setDiff(allTags, ["build", "build-all", "fullbuild", "style"]), @@ -184,17 +184,6 @@ local sulong_deps = common.deps.sulong; llvmBundled:: {}, - requireGCC:: { - packages+: { - gcc: "==6.1.0", - }, - }, - - # like requireGCC, but only on linux/amd64, ignored otherwise - optionalGCC:: { - packages+: if self.os == "linux" && self.arch == "amd64" then $.requireGCC.packages else {}, - }, - requireGMP:: { packages+: if self.os == "darwin" && self.arch == "aarch64" then { libgmp: "==6.2.1", diff --git a/sulong/docs/contributor/TOOLCHAIN.md b/sulong/docs/contributor/TOOLCHAIN.md index 8f24b651de7b..11bf84d3749d 100644 --- a/sulong/docs/contributor/TOOLCHAIN.md +++ b/sulong/docs/contributor/TOOLCHAIN.md @@ -159,13 +159,13 @@ On the implementation side, _the toolchain_ consists of multiple ingredients: The goal is to produce a GraalVM LLVM runtime executable result by simply pointing any build system to those wrappers, for example via `CC`/`CXX` environment variables or by setting `PATH`. -## Using a Prebuilt GraalVM as a Bootstrapping Toolchain +## Using a Prebuilt standalone as a Bootstrapping Toolchain -To speed up toolchain compilation during development, the `SULONG_BOOTSTRAP_GRAALVM` environment variable can be set -to a _prebuilt_ GraalVM. Sulong comes with a configuration file that makes building a bootstrapping GraalVM easy: +To speed up toolchain compilation during development, the `SULONG_BOOTSTRAP_STANDALONE` environment variable can be set +to a _prebuilt_ standalone. ```bash -$ mx --env toolchain-only build -$ export SULONG_BOOTSTRAP_GRAALVM=`mx --env toolchain-only graalvm-home` +$ mx --env ce-llvm-standalones build --dependencies SULONG_JVM_STANDALONE +$ export SULONG_BOOTSTRAP_STANDALONE=`mx --env ce-llvm-standalones path --output SULONG_JVM_STANDALONE` ``` > **WARNING**: *The bootstrapping GraalVM will not be rebuilt automatically. You are responsible for keeping it up-to-date.* diff --git a/sulong/mx.sulong/ce-llvm-standalones b/sulong/mx.sulong/ce-llvm-standalones index d0561b261efe..447a685a5d39 100644 --- a/sulong/mx.sulong/ce-llvm-standalones +++ b/sulong/mx.sulong/ce-llvm-standalones @@ -1,3 +1,5 @@ -DYNAMIC_IMPORTS=/substratevm,/vm -COMPONENTS=llp,llrl,llrlf,llrn,lg,svmnfi,tflm,tflsm -BUILD_TARGETS=GRAALVM_STANDALONES +DYNAMIC_IMPORTS=/tools,/compiler,/substratevm +COMPONENTS=SubstrateVM,Truffle SVM Macro,LibGraal +NATIVE_IMAGES=true +BUILD_TARGETS=SULONG_NATIVE_STANDALONE,SULONG_JVM_STANDALONE +GRAALVM_SKIP_ARCHIVE=true diff --git a/sulong/mx.sulong/mx_sulong.py b/sulong/mx.sulong/mx_sulong.py index 8a80739664e6..e59cdfcf0bba 100644 --- a/sulong/mx.sulong/mx_sulong.py +++ b/sulong/mx.sulong/mx_sulong.py @@ -47,6 +47,7 @@ import mx_sulong_gate import mx_sulong_unittest #pylint: disable=unused-import import mx_sulong_llvm_config +import mx_truffle # re-export custom mx project classes so they can be used from suite.py from mx_cmake import CMakeNinjaProject #pylint: disable=unused-import @@ -58,6 +59,7 @@ from mx_sulong_suite_constituents import DocumentationProject #pylint: disable=unused-import from mx_sulong_suite_constituents import HeaderProject #pylint: disable=unused-import from mx_sulong_suite_constituents import CopiedNativeProject #pylint: disable=unused-import +from mx_sdk_vm_ng import StandaloneLicenses, ThinLauncherProject, NativeImageLibraryProject, NativeImageExecutableProject, LanguageLibraryProject, DynamicPOMDistribution, DeliverableStandaloneArchive, ToolchainToolDistribution # pylint: disable=unused-import if sys.version_info[0] < 3: def _decode(x): @@ -102,6 +104,36 @@ def sulong_prefix_path(name): mx_subst.results_substitutions.register_with_arg('sulong_prefix', sulong_prefix_path) +# Functions called from suite.py + +def has_suite(name): + return mx.suite(name, fatalIfMissing=False) + +def is_ee(): + return has_suite('sulong-managed') + +def sulong_standalone_deps(): + deps = mx_truffle.resolve_truffle_dist_names() + if is_ee(): + # SULONG_ENTERPRISE and SULONG_MANAGED do not belong in the EE standalone of SULONG_NATIVE, but we want a single definition of libllvmvm. + # So we compromise here by including them. We do not use or distribute the EE standalone of SULONG_NATIVE so it does not matter. + # See also the comments in suite.py, in SULONG_*_STANDALONE_RELEASE_ARCHIVE. + deps += [ + 'sulong-managed:SULONG_ENTERPRISE', + 'sulong-managed:SULONG_MANAGED', + 'sulong-managed:SULONG_ENTERPRISE_NATIVE', + ] + return deps + +def libllvmvm_build_args(): + if is_ee() and not mx.is_windows(): + return [ + '-H:+AuxiliaryEngineCache', + '-H:ReservedAuxiliaryImageBytes=2145482548', + ] + else: + return [] + def testLLVMImage(image, imageArgs=None, testFilter=None, libPath=True, test=None, unittestArgs=None): mx_sulong_gate.testLLVMImage(image, imageArgs, testFilter, libPath, test, unittestArgs) @@ -281,7 +313,11 @@ def get_lli_path(fatalIfMissing=True): useJvm = False else: mx.abort(f"Unknown standalone type {standaloneMode}.") - path = mx_sdk_vm_impl.standalone_home("llvm", useJvm) + if is_ee(): + dist = "SULONG_MANAGED_JVM_STANDALONE" if useJvm else "SULONG_MANAGED_NATIVE_STANDALONE" + else: + dist = "SULONG_JVM_STANDALONE" if useJvm else "SULONG_NATIVE_STANDALONE" + path = mx.distribution(dist).output return os.path.join(path, 'bin', mx_subst.path_substitutions.substitute('')) @@ -387,13 +423,9 @@ def _get_toolchain_tool(name_tool): def create_toolchain_root_provider(name, dist): def provider(): - bootstrap_graalvm = mx.get_env('SULONG_BOOTSTRAP_GRAALVM') - if bootstrap_graalvm: - ret = os.path.join(bootstrap_graalvm, 'jre', 'languages', 'llvm', name) - if os.path.exists(ret): # jdk8 based graalvm - return ret - else: # jdk11+ based graalvm - return os.path.join(bootstrap_graalvm, 'languages', 'llvm', name) + bootstrap_standalone = mx.get_env('SULONG_BOOTSTRAP_STANDALONE') + if bootstrap_standalone: + return os.path.join(bootstrap_standalone, 'lib', 'sulong', name) return mx.distribution(dist).get_output() return provider @@ -408,7 +440,8 @@ def _lib_sub(program): return mx_subst.path_substitutions.substitute("".format(program)) class ToolchainConfig(object): - # Please keep this list in sync with Toolchain.java (method documentation) and ToolchainImpl.java (lookup switch block). + # Please keep this list in sync with Toolchain.java (method documentation) and ToolchainImpl.java (lookup switch block) + # and NativeToolchainWrapper. _llvm_tool_map = ["ar", "nm", "objcopy", "objdump", "ranlib", "readelf", "readobj", "strip"] _tool_map = { "CC": ["graalvm-{name}-clang", "graalvm-clang", "clang", "cc", "gcc"], diff --git a/sulong/mx.sulong/mx_sulong_gate.py b/sulong/mx.sulong/mx_sulong_gate.py index 75970c6294fd..d35f898d6d1c 100644 --- a/sulong/mx.sulong/mx_sulong_gate.py +++ b/sulong/mx.sulong/mx_sulong_gate.py @@ -38,8 +38,6 @@ import mx_sulong_suite_constituents import mx_sulong_unittest -import mx_sdk_vm - _suite = mx.suite('sulong') def _sulong_gate_unittest(title, test_suite, tasks, args, tags=None, testClasses=None, unittestArgs=None): @@ -169,11 +167,11 @@ def _unittest(title, test_suite, tags=None, testClasses=None, unittestArgs=None, if standaloneMode == "native": with Task('Build Native LLVM Standalone', tasks, tags=['standalone']) as t: - if t: mx.command_function('build')(['--dependencies', f'LLVM_NATIVE_STANDALONE_SVM_JAVA{mx_sdk_vm.base_jdk_version()}']) + if t: mx.command_function('build')(['--dependencies', f'SULONG_NATIVE_STANDALONE']) if standaloneMode == "jvm": with Task('Build Java LLVM Standalone', tasks, tags=['standalone']) as t: - if t: mx.command_function('build')(['--dependencies', f'LLVM_JAVA_STANDALONE_SVM_JAVA{mx_sdk_vm.base_jdk_version()}']) + if t: mx.command_function('build')(['--dependencies', f'SULONG_JVM_STANDALONE']) # Folders not containing tests: options, services, util _unittest('Benchmarks', 'SULONG_SHOOTOUT_TEST_SUITE', description="Language Benchmark game tests", testClasses=['ShootoutsSuite'], tags=['benchmarks', 'sulongMisc']) diff --git a/sulong/mx.sulong/suite.py b/sulong/mx.sulong/suite.py index a24e6e3170ed..55a8e00c0078 100644 --- a/sulong/mx.sulong/suite.py +++ b/sulong/mx.sulong/suite.py @@ -1,5 +1,5 @@ suite = { - "mxversion": "7.33.0", + "mxversion": "7.48.0", "name" : "sulong", "version" : "25.0.0", "release" : False, @@ -1649,6 +1649,64 @@ "testProject" : True, "defaultBuild" : False, }, + + "sulong_licenses": { + "class": "StandaloneLicenses", + "community_license_file": "LICENSE", + "community_3rd_party_license_file": "THIRD_PARTY_LICENSE.txt", + }, + + "sulong_thin_launcher": { + "class": "ThinLauncherProject", + "mainClass": "com.oracle.truffle.llvm.launcher.LLVMLauncher", + "jar_distributions": ["sulong:SULONG_LAUNCHER"], + "relative_home_paths": { + "llvm": "../lib/sulong", + }, + "relative_jre_path": "../jvm", + "relative_module_path": "../modules", + "relative_extracted_lib_paths": { + "truffle.attach.library": "../jvmlibs/", + "truffle.nfi.library": "../jvmlibs/", + }, + "liblang_relpath": "../lib/", + "defaultBuild": False, + }, + + "libllvmvm": { + "class": "LanguageLibraryProject", + "dependencies": [ + "SULONG_STANDALONE_DEPENDENCIES", + ], + "build_args": [ + # From mx.sulong/native-image.properties + "-H:+AddAllCharsets", + # Configure launcher + "-Dorg.graalvm.launcher.class=com.oracle.truffle.llvm.launcher.LLVMLauncher", + ], + "dynamicBuildArgs": "libllvmvm_build_args", + "defaultBuild": False, + }, + + "graalvm-native-tool": { + "class": "NativeImageExecutableProject", + "dependencies": [ + "sulong:SULONG_TOOLCHAIN_LAUNCHERS", + ], + "build_args": [ + "--initialize-at-build-time=com.oracle.truffle.llvm.toolchain.launchers", + "--gc=epsilon", + "-H:+UnlockExperimentalVMOptions", + "-H:-ParseRuntimeOptions", + "-H:-UnlockExperimentalVMOptions", + # configure LLVM path for toolchain wrapper + # the toolchain root is lib/sulong/native, LLVM is in lib/llvm-toolchain + "-Dorg.graalvm.llvm.relative.path=../../llvm-toolchain", + # the main class + "com.oracle.truffle.llvm.toolchain.launchers.NativeToolchainWrapper", + ], + "defaultBuild": False, + }, }, "distributions" : { @@ -1765,6 +1823,7 @@ "SULONG_CORE", "truffle:TRUFFLE_NFI", "truffle:TRUFFLE_NFI_LIBFFI", + "truffle:TRUFFLE_NFI_PANAMA", ], "maven" : { "artifactId" : "llvm-language-native", @@ -1938,6 +1997,186 @@ "license" : "BSD-new", }, + "SULONG_STANDALONE_DEPENDENCIES": { + "description": "Sulong standalone dependencies", + "class": "DynamicPOMDistribution", + "distDependencies": [ + "sulong:SULONG_LAUNCHER", + "sulong:SULONG_CORE", + "sulong:SULONG_API", + "sulong:SULONG_NFI", + "sulong:SULONG_NATIVE", + "sulong:SULONG_TOOLCHAIN_LAUNCHERS", + "sdk:TOOLS_FOR_STANDALONE", + ], + "dynamicDistDependencies": "sulong_standalone_deps", + "maven": False, + "defaultBuild": False, + }, + + "SULONG_NATIVE_TOOLS": { + "class": "ToolchainToolDistribution", + "tool_project": "graalvm-native-tool", + "tool_links": { + "graalvm-native-clang": ["graalvm-clang", "clang", "gcc", "cc"], + "graalvm-native-clang++": ["graalvm-clang++", "clang++", "g++", "c++"], + "graalvm-native-clang-cl": ["graalvm-clang-cl", "clang-cl", "cl"], + "graalvm-native-flang": ["graalvm-flang", "flang-new", "flang"], + "graalvm-native-ld": ["lld", "lld-link", "ld.lld", "ld", "ld64"], + "llvm-ar": ["ar"], + "llvm-nm": ["nm"], + "llvm-objcopy": ["objcopy"], + "llvm-objdump": ["objdump"], + "llvm-ranlib": ["ranlib"], + "llvm-readelf": ["readelf"], + "llvm-readobj": ["readobj"], + "llvm-strip": ["strip"], + }, + "maven": False, + "defaultBuild": False, + }, + + "SULONG_NATIVE_AND_LLVM_TOOLCHAIN": { + "description": "Layout for Sulong native toolchain and llvm-toolchain", + "type": "dir", + "platformDependent": True, + "platforms": "local", + "layout": { + "lib/llvm-toolchain/": { + "source_type": "extracted-dependency", + "dependency": "sdk:LLVM_TOOLCHAIN", + "dereference": "never", + }, + + "lib/sulong/": [ + "extracted-dependency:SULONG_CORE_HOME", + "extracted-dependency:SULONG_GRAALVM_DOCS", + "extracted-dependency:SULONG_BITCODE_HOME", + "extracted-dependency:SULONG_NATIVE_HOME", + ], + + "lib/sulong/native/bin/": { + "source_type": "dependency", + "dependency": "SULONG_NATIVE_TOOLS", + "path": "*", + "dereference": "never", + }, + }, + "defaultBuild": False, + }, + + "SULONG_STANDALONE_COMMON": { + "description": "Common layout for Native and JVM standalones", + "type": "dir", + "platformDependent": True, + "platforms": "local", + "layout": { + "./": [ + "dependency:sulong_licenses/*", + { + "source_type": "dependency", + "dependency": "SULONG_NATIVE_AND_LLVM_TOOLCHAIN", + "path": "*", + "dereference": "never", + }, + ], + "bin/": "dependency:sulong_thin_launcher", + "release": "dependency:sdk:STANDALONE_JAVA_HOME/release", + }, + "defaultBuild": False, + }, + + "SULONG_LIBLLVMVM": { + "description": "libllvmvm as a layout, so it can be reused in sulong-managed", + "type": "dir", + "platformDependent": True, + "platforms": "local", + "layout": { + "lib/": [ + "dependency:libllvmvm", + ], + }, + "defaultBuild": False, + }, + + "SULONG_NATIVE_STANDALONE": { + "description": "Sulong Native standalone", + "type": "dir", + "platformDependent": True, + "platforms": "local", + "layout": { + "./": [ + "dependency:SULONG_LIBLLVMVM/*", + { + "source_type": "dependency", + "dependency": "SULONG_STANDALONE_COMMON", + "path": "*", + "dereference": "never", + }, + ], + }, + "defaultBuild": False, + }, + + "SULONG_JVM_STANDALONE": { + "description": "Sulong JVM standalone", + "type": "dir", + "platformDependent": True, + "platforms": "local", + "layout": { + "./": [ + { + "source_type": "dependency", + "dependency": "SULONG_STANDALONE_COMMON", + "path": "*", + "dereference": "never", + }, + ], + "jvm/": { + "source_type": "dependency", + "dependency": "sdk:STANDALONE_JAVA_HOME", + "path": "*", + "exclude": [ + # Native Image-related + "bin/native-image*", + "lib/static", + "lib/svm", + "lib/", + "lib/", + # Unnecessary and big + "lib/src.zip", + "jmods", + ], + }, + "jvmlibs/": [ + "extracted-dependency:truffle:TRUFFLE_ATTACH_GRAALVM_SUPPORT", + "extracted-dependency:truffle:TRUFFLE_NFI_NATIVE_GRAALVM_SUPPORT", + ], + "modules/": [ + "classpath-dependencies:SULONG_STANDALONE_DEPENDENCIES", + ], + }, + "defaultBuild": False, + }, + + "SULONG_NATIVE_STANDALONE_RELEASE_ARCHIVE": { + "class": "DeliverableStandaloneArchive", + "platformDependent": True, + "standalone_dist": "SULONG_NATIVE_STANDALONE", + "community_archive_name": "llvm-community", + "enterprise_archive_name": "llvm-unused", # should not be used as it lacks the managed toolchain + "defaultBuild": False, + }, + + "SULONG_JVM_STANDALONE_RELEASE_ARCHIVE": { + "class": "DeliverableStandaloneArchive", + "platformDependent": True, + "standalone_dist": "SULONG_JVM_STANDALONE", + "community_archive_name": "llvm-community-jvm", + "enterprise_archive_name": "llvm-unused-jvm", # should not be used as it lacks the managed toolchain + "defaultBuild": False, + }, + "SULONG_NATIVE_BITCODE_RESOURCES" : { "description" : "Contains the runtime dependencies needed by the LLVM runtime in native mode.", "type" : "dir", @@ -1984,6 +2223,17 @@ }, "SULONG_TOOLCHAIN_LAUNCHERS": { + "moduleInfo" : { + "name" : "org.graalvm.llvm.native_toolchain_wrappers", + "exports" : [ + "com.oracle.truffle.llvm.toolchain.launchers to org.graalvm.launcher", + # "com.oracle.truffle.llvm.toolchain.launchers.common to org.graalvm.llvm.managed_toolchain_wrappers", + # "com.oracle.truffle.llvm.toolchain.launchers to org.graalvm.llvm.managed_toolchain_wrappers", + "com.oracle.truffle.llvm.toolchain.launchers.common", # TODO ideally use the above but doesn't work + "com.oracle.truffle.llvm.toolchain.launchers", # TODO ideally use the above but doesn't work + ], + }, + "useModulePath" : True, "subDir" : "projects", "dependencies" : ["com.oracle.truffle.llvm.toolchain.launchers"], "distDependencies" : ["sdk:LAUNCHER_COMMON"], diff --git a/sulong/mx.sulong/toolchain-only b/sulong/mx.sulong/toolchain-only deleted file mode 100644 index 74d1db2875d3..000000000000 --- a/sulong/mx.sulong/toolchain-only +++ /dev/null @@ -1,4 +0,0 @@ -DYNAMIC_IMPORTS=/substratevm,/vm -COMPONENTS=GraalVM compiler,Truffle Macro,LLVM Runtime Native,LLVM.org toolchain -NATIVE_IMAGES=graalvm-native-clang,graalvm-native-clang-cl,graalvm-native-clang++,graalvm-native-flang,graalvm-native-ld,graalvm-native-binutil -DISABLE_POLYGLOT=true diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/ToolchainImpl.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/ToolchainImpl.java index 11ea673d30bb..fd8ab4fdce03 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/ToolchainImpl.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/ToolchainImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. * * All rights reserved. * @@ -73,7 +73,7 @@ public TruffleFile getToolPath(String tool) { /** * Please keep this list in sync with Toolchain.java (method documentation) and mx_sulong.py's - * ToolchainConfig::_tool_map. + * ToolchainConfig::_tool_map and NativeToolchainWrapper. */ private TruffleFile getToolPathImpl(String tool) { diff --git a/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/AbstractBinUtil.java b/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/AbstractBinUtil.java deleted file mode 100644 index 47edf86e1bbb..000000000000 --- a/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/AbstractBinUtil.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2024, 2024, Oracle and/or its affiliates. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be used to - * endorse or promote products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.oracle.truffle.llvm.toolchain.launchers; - -import com.oracle.truffle.llvm.toolchain.launchers.common.Driver; -import org.graalvm.nativeimage.ProcessProperties; - -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Optional; - -public abstract class AbstractBinUtil { - - public final void run(String[] args) { - String toolName = getProcessName(); - - if (toolName == null) { - System.err.println("Error: Could not figure out process name"); - System.exit(1); - } - - if (!toolName.startsWith("llvm-")) { - toolName = "llvm-" + toolName; - } - - final Path toolPath = getTargetPath(toolName); - runTool(toolPath, args); - } - - public static void runTool(Path toolPath, String[] args) { - ArrayList utilArgs = new ArrayList<>(args.length + 1); - utilArgs.add(toolPath.toString()); - if (args.length > 0) { - utilArgs.addAll(Arrays.asList(args)); - } - ProcessBuilder pb = new ProcessBuilder(utilArgs).redirectError(ProcessBuilder.Redirect.INHERIT).redirectInput(ProcessBuilder.Redirect.INHERIT).redirectOutput(ProcessBuilder.Redirect.INHERIT); - Process p = null; - try { - p = pb.start(); - p.waitFor(); - System.exit(p.exitValue()); - } catch (IOException e) { - System.err.println("Error: " + e.getMessage()); - Driver.printMissingToolMessage(Optional.ofNullable(toolPath.getParent()).map(Path::getParent).map(Path::toString).orElse("")); - System.exit(1); - } catch (InterruptedException e) { - if (p != null) { - p.destroyForcibly(); - } - System.err.println("Error: Subprocess interrupted: " + e.getMessage()); - System.exit(1); - } - } - - private static boolean isWindows() { - return System.getProperty("os.name").startsWith("Windows"); - } - - public static String getProcessName() { - String binPathName = System.getProperty("org.graalvm.launcher.executablename"); - - if (binPathName == null) { - if (isWindows()) { - binPathName = System.getenv("GRAALVM_ARGUMENT_VECTOR_PROGRAM_NAME"); - if (binPathName == null) { - return null; - } - } else { - if (ProcessProperties.getArgumentVectorBlockSize() <= 0) { - return null; - } - binPathName = ProcessProperties.getArgumentVectorProgramName(); - - if (binPathName == null) { - return null; - } - } - } - - Path p = Paths.get(binPathName); - Path f = p.getFileName(); - - if (f == null) { - return null; - } - - String result = f.toString(); - - if (isWindows()) { - result = result.replace(".cmd", ".exe"); - } - - return result; - } - - protected abstract Path getTargetPath(String binUtilName); - -} diff --git a/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/AbstractToolchainWrapper.java b/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/AbstractToolchainWrapper.java new file mode 100644 index 000000000000..752e0d71418e --- /dev/null +++ b/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/AbstractToolchainWrapper.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.oracle.truffle.llvm.toolchain.launchers; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; + +import org.graalvm.nativeimage.ProcessProperties; + +public abstract class AbstractToolchainWrapper { + + /** + * The path of the LLVM distribution, relative to the toolchain root. This is set at + * native-image build time. + */ + private static final String RELATIVE_LLVM_PATH = System.getProperty("org.graalvm.llvm.relative.path"); + + private static ToolchainWrapperConfig config; + + public static final ToolchainWrapperConfig getConfig() { + return config; + } + + public record ToolchainWrapperConfig(String toolName, Path toolchainPath, Path llvmPath) { + } + + public interface Tool { + + void run(String[] args); + } + + private static boolean isWindows() { + return System.getProperty("os.name").startsWith("Windows"); + } + + private static Path getCurrentExecutablePath() { + final String path = ProcessProperties.getExecutableName(); + return path == null ? null : Paths.get(path); + } + + private static String getFile(Path path) { + Path file = path.getFileName(); + return file != null ? file.toString() : null; + } + + protected void run(String[] args) { + Path executablePath = getCurrentExecutablePath(); + if (executablePath == null) { + System.err.println("Error: Could not determine current executable path"); + System.exit(1); + } + + // executablePath is /bin/tool + Path toolchainPath = executablePath.getParent(); + if (toolchainPath != null) { + toolchainPath = toolchainPath.getParent(); + } + if (toolchainPath == null) { + System.err.println("Error: Could not find toolchain path"); + System.exit(1); + } + Path llvmPath = toolchainPath.resolve(RELATIVE_LLVM_PATH).normalize(); + + String programName; + if (isWindows()) { + // set by the exe_link_template.cmd wrapper script + programName = System.getenv("GRAALVM_ARGUMENT_VECTOR_PROGRAM_NAME"); + } else { + programName = ProcessProperties.getArgumentVectorProgramName(); + } + + String binPathName; + if (programName == null) { + binPathName = getFile(executablePath); + } else { + binPathName = getFile(Paths.get(programName)); + } + + if (binPathName == null) { + System.err.println("Error: Could not figure out process name"); + System.exit(1); + } + + String toolName = binPathName; + if (isWindows()) { + if (toolName.endsWith(".cmd") || toolName.endsWith(".exe")) { + toolName = toolName.substring(0, toolName.length() - 4); + } + } + + for (String prefix : getStrippedPrefixes()) { + if (toolName.startsWith(prefix)) { + toolName = toolName.substring(prefix.length()); + } + } + + assert config == null : "AbstractToolchainWrapper.run called twice?"; + config = new ToolchainWrapperConfig(toolName, toolchainPath, llvmPath); + + getTool(toolName).run(args); + } + + protected Iterable getStrippedPrefixes() { + return Collections.emptyList(); + } + + protected abstract Tool getTool(String toolName); +} diff --git a/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/BinUtil.java b/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/BinUtil.java index 247dceccd195..b967cdc94aae 100644 --- a/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/BinUtil.java +++ b/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/BinUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. * * All rights reserved. * @@ -29,18 +29,72 @@ */ package com.oracle.truffle.llvm.toolchain.launchers; -import com.oracle.truffle.llvm.toolchain.launchers.common.Driver; - +import java.io.IOException; import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Optional; + +import org.graalvm.nativeimage.ProcessProperties; -public final class BinUtil extends AbstractBinUtil { +import com.oracle.truffle.llvm.toolchain.launchers.AbstractToolchainWrapper.ToolchainWrapperConfig; +import com.oracle.truffle.llvm.toolchain.launchers.common.Driver; + +public final class BinUtil { public static void main(String[] args) { - new BinUtil().run(args); + ToolchainWrapperConfig config = AbstractToolchainWrapper.getConfig(); + + String toolName; + if (config != null) { + toolName = config.toolName(); + } else { + // this is the boostrap toolchain... + toolName = System.getProperty("org.graalvm.launcher.executablename"); + + // ... or a legacy GraalVM + if (toolName == null) { + toolName = ProcessProperties.getArgumentVectorProgramName(); + } + + Path toolPath = Paths.get(toolName).getFileName(); + if (toolPath != null) { + toolName = toolPath.toString(); + } + } + + if (!toolName.startsWith("llvm-")) { + toolName = "llvm-" + toolName; + } + + final Path toolPath = Driver.getLLVMBinDir().resolve(toolName); + runTool(toolPath, args); } - @Override - protected Path getTargetPath(String binUtilName) { - return Driver.getLLVMBinDir().resolve(binUtilName); + public static void runTool(Path toolPath, String[] args) { + ArrayList utilArgs = new ArrayList<>(args.length + 1); + utilArgs.add(toolPath.toString()); + if (args.length > 0) { + utilArgs.addAll(Arrays.asList(args)); + } + ProcessBuilder pb = new ProcessBuilder(utilArgs).redirectError(ProcessBuilder.Redirect.INHERIT).redirectInput(ProcessBuilder.Redirect.INHERIT).redirectOutput(ProcessBuilder.Redirect.INHERIT); + Process p = null; + try { + p = pb.start(); + p.waitFor(); + System.exit(p.exitValue()); + } catch (IOException e) { + System.err.println("Error: " + e.getMessage()); + Driver.printMissingToolMessage(Optional.ofNullable(toolPath.getParent()).map(Path::getParent).map(Path::toString).orElse("")); + System.exit(1); + } catch (InterruptedException e) { + if (p != null) { + p.destroyForcibly(); + } + System.err.println("Error: Subprocess interrupted: " + e.getMessage()); + System.exit(1); + } } + } diff --git a/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/NativeToolchainWrapper.java b/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/NativeToolchainWrapper.java new file mode 100644 index 000000000000..908b2e7e63f2 --- /dev/null +++ b/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/NativeToolchainWrapper.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.oracle.truffle.llvm.toolchain.launchers; + +import java.util.Arrays; + +public final class NativeToolchainWrapper extends AbstractToolchainWrapper { + + public static void main(String[] args) { + new NativeToolchainWrapper().run(args); + } + + @Override + protected Iterable getStrippedPrefixes() { + return Arrays.asList("graalvm-native-", "graalvm-"); + } + + @Override + protected Tool getTool(String toolName) { + return switch (toolName) { + case "clang", "cc", "gcc" -> Clang::main; + case "clang++", "c++", "g++" -> ClangXX::main; + case "clang-cl", "cl" -> ClangCL::main; + case "ld", "ld.lld", "lld", "lld-link", "ld64" -> Linker::main; + case "flang-new", "flang" -> Flang::main; + default -> BinUtil::main; + }; + } + +} diff --git a/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/common/Driver.java b/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/common/Driver.java index 621427f0de61..bc0e7713ef58 100644 --- a/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/common/Driver.java +++ b/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/common/Driver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. * * All rights reserved. * @@ -32,6 +32,9 @@ import org.graalvm.home.HomeFinder; import org.graalvm.home.Version; +import com.oracle.truffle.llvm.toolchain.launchers.AbstractToolchainWrapper; +import com.oracle.truffle.llvm.toolchain.launchers.AbstractToolchainWrapper.ToolchainWrapperConfig; + import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -113,30 +116,37 @@ public static Arch getCurrent() { } } - private static Path getRuntimeDir() { - Path runtimeDir = HomeFinder.getInstance().getHomeFolder(); - if (runtimeDir == null) { - throw new IllegalStateException("Could not find GraalVM home"); - } - return runtimeDir; - } - public static Path getLLVMBinDir() { + // allow manually overriding custom LLVM path final String property = System.getProperty("llvm.bin.dir"); if (property != null) { return Paths.get(property); } - // TODO (GR-18389): Set only for standalones currently + // look up LLVM path relative to the toolchain wrapper + ToolchainWrapperConfig config = AbstractToolchainWrapper.getConfig(); + if (config != null) { + return config.llvmPath().resolve("bin"); + } + + // TODO (GR-18389): Set only for old-style standalones Path toolchainHome = HomeFinder.getInstance().getLanguageHomes().get("llvm-toolchain"); if (toolchainHome != null) { return toolchainHome.resolve("bin"); } - return getRuntimeDir().resolve("lib").resolve("llvm").resolve("bin"); + // TODO: Set only for old-style monolithic GraalVM builds + return HomeFinder.getInstance().getHomeFolder().resolve("lib").resolve("llvm").resolve("bin"); } public static Path getSulongHome() { + ToolchainWrapperConfig config = AbstractToolchainWrapper.getConfig(); + if (config != null) { + // the toolchain root is /native + return config.toolchainPath().getParent(); + } + + // TODO (GR-18389): Set only for old-style standalones final Path sulongHome = HomeFinder.getInstance().getLanguageHomes().get("llvm"); if (sulongHome != null) { return sulongHome; diff --git a/truffle/mx.truffle/mx_truffle.py b/truffle/mx.truffle/mx_truffle.py index 3fac072093e6..6b274682f275 100644 --- a/truffle/mx.truffle/mx_truffle.py +++ b/truffle/mx.truffle/mx_truffle.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2025, 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 @@ -1611,7 +1611,7 @@ def _qualname(distribution_name): mx.add_argument('--polyglot-isolates', action='store', help='Comma-separated list of languages for which the polyglot isolate library should be built. Setting the value to `true` builds all polyglot isolate libraries.') -class PolyglotIsolateProject(mx_sdk_vm_ng.LanguageLibraryProject): +class PolyglotIsolateProject(mx_sdk_vm_ng.NativeImageLibraryProject): """ A language library project dedicated to construct a language polyglot isolate library. Instances are created by register_polyglot_isolate_distributions when a language diff --git a/vm/mx.vm/mx_vm.py b/vm/mx.vm/mx_vm.py index de4e96cc27f7..5b36f6a7fac8 100644 --- a/vm/mx.vm/mx_vm.py +++ b/vm/mx.vm/mx_vm.py @@ -161,9 +161,7 @@ def local_path_to_url(args): mx_sdk_vm.register_vm_config('ce-fastr', ce_fastr_components, _suite) mx_sdk_vm.register_vm_config('ce-no_native', ce_no_native_components, _suite) mx_sdk_vm.register_vm_config('libgraal', ['cmp', 'lg', 'sdkc', 'tflc'], _suite) -mx_sdk_vm.register_vm_config('toolchain-only', ['antlr4', 'sdk', 'sdkni', 'sdkc', 'sdkl', 'tfl', 'tfla', 'tflc', 'tflm', 'nfi-libffi', 'nfi', 'cmp', 'llp', 'llrc', 'llrlf', 'llrn'], _suite) mx_sdk_vm.register_vm_config('libgraal-bash', llvm_components + ['cmp', 'gvm', 'lg', 'nfi-libffi', 'nfi', 'sdk', 'sdkni', 'sdkc', 'sdkl', 'tfl', 'tfla', 'tflc', 'tflm'], _suite, env_file=False) -mx_sdk_vm.register_vm_config('toolchain-only-bash', llvm_components + ['antlr4', 'tfl', 'tfla', 'tflc', 'tflm', 'gvm', 'llp', 'nfi-libffi', 'nfi', 'svml', 'sdk', 'sdkni', 'sdkc', 'sdkl', 'llrc', 'llrlf', 'llrn', 'cmp'], _suite, env_file=False) mx_sdk_vm.register_vm_config('ce', llvm_components + ['antlr4', 'sjsvm', 'sllvmvm', 'bnative-image', 'srubyvm', 'pynl', 'spythonvm', 'pyn', 'cmp', 'gwa', 'gwal', 'icu4j', 'xz', 'js', 'jsl', 'jss', 'lg', 'llp', 'nfi-libffi', 'nfi', 'ni', 'nil', 'pbm', 'pmh', 'pbi', 'rby', 'rbyl', 'rgx', 'sdk', 'sdkni', 'sdkc', 'sdkl', 'llrc', 'llrn', 'llrl', 'llrlf', 'snative-image-agent', 'snative-image-diagnostics-agent', 'svm', 'svmt', 'svmnfi', 'svmsl', 'swasmvm', 'tfl', 'tfla', 'tflc', 'tflm'], _suite, env_file='polybench-ce') mx_sdk_vm.register_vm_config('ce', ['bnative-image', 'bpolybench', 'cmp', 'icu4j', 'xz', 'lg', 'nfi', 'ni', 'nil', 'pbi', 'pbm', 'pmh', 'sdk', 'sdkni', 'sdkc', 'sdkl', 'snative-image-agent', 'snative-image-diagnostics-agent', 'svm', 'svmt', 'svmnfi', 'svmsl', 'tfl', 'tfla', 'tflc', 'tflm'], _suite, dist_name='ce', env_file='polybench-ctw-ce') mx_sdk_vm.register_vm_config('ce', ['pbm', 'pmh', 'pbi', 'ni', 'icu4j', 'xz', 'js', 'jsl', 'jss', 'lg', 'nfi-libffi', 'nfi', 'tfl', 'tfla', 'tflc', 'svm', 'svmt', 'nil', 'rgx', 'sdk', 'sdkni', 'sdkc', 'sdkl', 'cmp', 'tflm', 'svmnfi', 'svmsl', 'bnative-image', 'sjsvm', 'snative-image-agent', 'snative-image-diagnostics-agent'], _suite, env_file='polybench-nfi-ce') diff --git a/vm/mx.vm/toolchain-only b/vm/mx.vm/toolchain-only deleted file mode 100644 index 8f3f39a0b6ed..000000000000 --- a/vm/mx.vm/toolchain-only +++ /dev/null @@ -1,4 +0,0 @@ -DYNAMIC_IMPORTS=/compiler,/sdk,/substratevm,/sulong,/truffle -COMPONENTS=antlr4,cmp,llp,llrc,llrn,nfi-libffi,sdk,sdkl,tfl,tfla,tflc,tflm -NATIVE_IMAGES=graalvm-native-binutil,graalvm-native-clang,graalvm-native-clang-cl,graalvm-native-clang++,graalvm-native-flang,graalvm-native-ld -DISABLE_INSTALLABLES=False