def contents(self, tool, exe): # platform support all_params = '%*' if mx.is_windows() else '"$@"' _quote = _quote_windows if mx.is_windows() else pipes.quote # build command line java = mx.get_jdk().java classpath_deps = [ dep for dep in self.subject.buildDependencies if isinstance(dep, mx.ClasspathDependency) ] extra_props = [ '-Dorg.graalvm.launcher.executablename="{}"'.format(exe) ] main_class = self.subject.suite.toolchain._tool_to_main(tool) # add jvm args from dependencies jvm_args = [ _quote(arg) for arg in mx.get_runtime_jvm_args(classpath_deps) ] # add properties from the project if hasattr(self.subject, "getJavaProperties"): for key, value in sorted(self.subject.getJavaProperties().items()): jvm_args.append("-D" + key + "=" + value) command = [java] + jvm_args + extra_props + [main_class, all_params] # create script if mx.is_windows(): return "@echo off\n" + " ".join(command) + "\n" else: return "#!/usr/bin/env bash\n" + "exec " + " ".join(command) + "\n"
def asm_rule(self): assert mx.is_windows() self.n.rule( 'cpp', command= 'cl -nologo -showIncludes -EP -P $includes $cflags -c $in -Fi$out', description='CPP $out', deps='msvc') self.newline() self.n.rule('asm', command='ml64 -nologo -Fo$out -c $in', description='ASM $out') self.newline() def preprocessed(source_file): output = os.path.splitext(source_file)[0] + '.asm' return self.n.build(output, 'cpp', self._resolve(source_file))[0] def build(source_file): output = os.path.splitext(source_file)[0] + '.obj' return self.n.build(output, 'asm', preprocessed(source_file))[0] return build
def _ensure_vm_built(): # build "jvm" config used by native-image and native-image-configure commands config = graalvm_jvm_configs[-1] rebuild_vm = False mx.ensure_dir_exists(svmbuild_dir()) if not mx.is_windows(): vm_link = join(svmbuild_dir(), 'vm') if not os.path.exists(vm_link): rebuild_vm = True if os.path.lexists(vm_link): os.unlink(vm_link) vm_linkname = os.path.relpath(_vm_home(config), dirname(vm_link)) os.symlink(vm_linkname, vm_link) rev_file_name = join(svmbuild_dir(), 'vm-rev') rev_value = svm_suite().vc.parent(svm_suite().vc_dir) if not os.path.exists(rev_file_name): rebuild_vm = True else: with open(rev_file_name, 'r') as f: if f.read() != rev_value: rebuild_vm = True if rebuild_vm: with open(rev_file_name, 'w') as f: f.write(rev_value) build_native_image_image(config)
def launchers(self): for tool in self.suite.toolchain._supported_tools(): for exe in self.suite.toolchain._tool_to_aliases(tool): if mx.is_windows() and exe.endswith('.exe'): exe = exe[:-4] + ".cmd" result = os.path.join(self.get_output_root(), exe) yield result, tool, exe
def cc_rule(self, cxx=False): if mx.is_windows(): command = 'cl -nologo -showIncludes $includes $cflags -c $in -Fo$out' depfile = None deps = 'msvc' else: command = '%s -MMD -MF $out.d $includes $cflags -c $in -o $out' % ( 'g++' if cxx else 'gcc') depfile = '$out.d' deps = 'gcc' rule = 'cxx' if cxx else 'cc' self.n.rule(rule, command=command, description='%s $out' % rule.upper(), depfile=depfile, deps=deps) self.newline() def build(source_file): output = os.path.splitext(source_file)[0] + ( '.obj' if mx.is_windows() else '.o') return self.n.build(output, rule, self._resolve(source_file))[0] return build
def contents(self, tool, exe): # platform support all_params = '"%*"' if mx.is_windows() else '"$@"' _quote = _quote_windows if mx.is_windows() else pipes.quote # build command line java = mx.get_jdk().java classpath_deps = [dep for dep in self.subject.buildDependencies if isinstance(dep, mx.ClasspathDependency)] extra_props = ['-Dorg.graalvm.launcher.executablename="{}"'.format(exe)] main_class = self.subject.suite.toolchain._tool_to_main(tool) jvm_args = [_quote(arg) for arg in mx.get_runtime_jvm_args(classpath_deps)] command = [java] + jvm_args + extra_props + [main_class, all_params] # create script if mx.is_windows(): return "@echo off\n" + " ".join(command) + "\n" else: return "#!/usr/bin/env bash\n" + "exec " + " ".join(command) + "\n"
def run(self, *args, **kwargs): # Hack: disable autocrlf on Windows but re-use the caching-related code in GitConfig.clone if mx.is_windows() and len(args) == 1 and len(args[0]) >= 2 and args[0][0] == 'git' and args[0][1] == 'clone': _cmd = args[0] _new_cmd = _cmd[:2] + ['-c', 'core.autocrlf=false'] + _cmd[2:] return super(NoCRLFGitConfig, self).run(_new_cmd, **kwargs) else: return super().run(*args, **kwargs)
def intellij_read_sdks(): sdks = dict() if mx.is_linux() or mx.is_openbsd() or mx.is_sunos() or mx.is_windows(): xmlSdks = glob.glob(os.path.expanduser("~/.IdeaIC*/config/options/jdk.table.xml")) + \ glob.glob(os.path.expanduser("~/.IntelliJIdea*/config/options/jdk.table.xml")) + \ glob.glob(os.path.expanduser("~/.config/JetBrains/IdeaIC*/options/jdk.table.xml")) + \ glob.glob(os.path.expanduser("~/.config/JetBrains/IntelliJIdea*/options/jdk.table.xml")) elif mx.is_darwin(): xmlSdks = \ glob.glob(os.path.expanduser("~/Library/Application Support/JetBrains/IdeaIC*/options/jdk.table.xml")) + \ glob.glob(os.path.expanduser("~/Library/Application Support/JetBrains/IntelliJIdea*/options/jdk.table.xml")) + \ glob.glob(os.path.expanduser("~/Library/Preferences/IdeaIC*/options/jdk.table.xml")) + \ glob.glob(os.path.expanduser("~/Library/Preferences/IntelliJIdea*/options/jdk.table.xml")) else: mx.warn("Location of IntelliJ SDK definitions on {} is unknown".format(mx.get_os())) return sdks if len(xmlSdks) == 0: mx.warn("IntelliJ SDK definitions not found") return sdks verRE = re.compile(r'^.*[/\\]\.?(IntelliJIdea|IdeaIC)([^/\\]+)[/\\].*$') def verSort(path): match = verRE.match(path) return match.group(2) + (".a" if match.group(1) == "IntellijIC" else ".b") xmlSdks.sort(key=verSort) xmlSdk = xmlSdks[-1] # Pick the most recent IntelliJ version, preferring Ultimate over Community edition. mx.log("Using SDK definitions from {}".format(xmlSdk)) versionRegexes = {} versionRegexes[intellij_java_sdk_type] = re.compile(r'^java\s+version\s+"([^"]+)"$|^version\s+(.+)$|^([\d._]+)$') versionRegexes[intellij_python_sdk_type] = re.compile(r'^Python\s+(.+)$') # Examples: # truffleruby 19.2.0-dev-2b2a7f81, like ruby 2.6.2, Interpreted JVM [x86_64-linux] # ver.2.2.4p230 ( revision 53155) p230 versionRegexes[intellij_ruby_sdk_type] = re.compile(r'^\D*(\d[^ ,]+)') for sdk in etreeParse(xmlSdk).getroot().findall("component[@name='ProjectJdkTable']/jdk[@version='2']"): name = sdk.find("name").get("value") kind = sdk.find("type").get("value") home = realpath(os.path.expanduser(sdk.find("homePath").get("value").replace('$USER_HOME$', '~'))) if home.find('$APPLICATION_HOME_DIR$') != -1: # Don't know how to convert this into a real path so ignore it continue versionRE = versionRegexes.get(kind) if not versionRE or sdk.find("version") is None: # ignore unknown kinds continue match = versionRE.match(sdk.find("version").get("value")) if match: version = match.group(1) sdks[home] = {'name': name, 'type': kind, 'version': version} mx.logv("Found SDK {} with values {}".format(home, sdks[home])) else: mx.warn(u"Couldn't understand Java version specification \"{}\" for {} in {}".format(sdk.find("version").get("value"), home, xmlSdk)) return sdks
def ar_rule(self): if mx.is_windows(): command = 'lib -nologo -out:$out $in' else: command = 'ar -rc $out $in' self.n.rule('ar', command=command, description='AR $out') self.newline() return lambda archive, members: self.n.build(archive, 'ar', members)[0]
def _lib_versioned(arg): name, version = arg.split('.') if mx.is_darwin(): return "lib" + name + "." + version + ".dylib" elif mx.is_linux() or mx.is_openbsd() or mx.is_sunos(): return "lib" + name + ".so." + version elif mx.is_windows(): return name + ".dll" else: mx.abort('unsupported os')
def cflags(self): default_cflags = [] if mx.is_windows() and mx.get_jdk(tag=mx.DEFAULT_JDK_TAG).javaCompliance >= '11': default_cflags += ['-FS'] # necessary until GR-16572 is resolved if self._kind == self._kinds['shared_lib']: default_cflags += dict( windows=['-MD'], ).get(mx.get_os(), ['-fPIC']) return default_cflags + super(DefaultNativeProject, self).cflags
def generate_manifest(self, path): unsupported_source_files = list(self._source['files'].viewkeys() - {'.h', '.c', '.cc', '.S'}) if unsupported_source_files: mx.abort( '{} source files are not supported by default native projects'. format(unsupported_source_files)) with NinjaManifestGenerator(self, open(path, 'w')) as gen: gen.comment('Project rules') cc = cxx = asm = None if self.c_files: cc = gen.cc_rule() if self.cxx_files: cxx = gen.cc_rule(cxx=True) if self.asm_sources: asm = gen.asm_rule() if mx.is_windows( ) else cc if cc else gen.cc_rule() ar = link = None if self._kind == self._kinds['static_lib']: ar = gen.ar_rule() else: link = gen.link_rule(cxx=bool(self.cxx_files)) gen.variables( cflags=self.cflags, ldflags=self.ldflags if link else None, ldlibs=self.ldlibs if link else None, ) gen.include( collections.OrderedDict.fromkeys( # remove the duplicates while maintaining the ordering [mx.dirname(h_file) for h_file in self.h_files] + list( itertools.chain.from_iterable( getattr(d, 'include_dirs', []) for d in self.buildDependencies))).keys()) gen.comment('Compiled project sources') object_files = [cc(f) for f in self.c_files] gen.newline() object_files += [cxx(f) for f in self.cxx_files] gen.newline() object_files += [asm(f) for f in self.asm_sources] gen.newline() gen.comment('Project deliverable') if self._kind == self._kinds['static_lib']: ar(self._target, object_files) else: link( self._target, object_files + list( itertools.chain.from_iterable( getattr(d, 'libs', []) for d in self.buildDependencies)))
def link_rule(self, cxx=False): if mx.is_windows(): command = 'link -nologo $ldflags -out:$out $in $ldlibs' else: command = '%s $ldflags -o $out $in $ldlibs' % ('g++' if cxx else 'gcc') self.n.rule('link', command=command, description='LINK $out') self.newline() return lambda program, files: self.n.build(program, 'link', files)[0]
def native_image_configure_on_jvm(args, **kwargs): _ensure_vm_built() if mx.is_windows(): config = graalvm_jvm_configs[-1] executable = vm_executable_path('native-image-configure', config) else: vm_link = join(svmbuild_dir(), 'vm') executable = join(vm_link, 'bin', 'native-image-configure') if not exists(executable): mx.abort("Can not find " + executable + "\nDid you forget to build? Try `mx build`") mx.run([executable, '-H:CLibraryPath=' + clibrary_libpath()] + args, **kwargs)
def parse_jar_suite_benchmark(self, args): if "-cp" not in args: mx.abort("Suite must specify -cp.") classpath = args[args.index("-cp") + 1] delimiter = ";" if mx.is_windows() else ":" jars = classpath.split(delimiter) jar = next(iter([jar for jar in jars if jar.endswith(BENCHMARK_JAR_SUFFIX)]), None) if jar is None: mx.abort("No benchmark jar file is specified in the classpath.") suite, benchmark = self.parse_suite_benchmark(args) return jar, suite, benchmark
def build_native_image_image(config=None, args=None): config = config or graalvm_config() mx.log('Building GraalVM with native-image in ' + _vm_home(config)) env = os.environ.copy() if mx.version < mx.VersionSpec("5.219"): mx.warn("mx version is older than 5.219, SVM's GraalVM build will not be built with links.\nConsider updating mx to improve IDE compile-on-save workflow.") if not mx.is_windows(): if 'LINKY_LAYOUT' not in env: env['LINKY_LAYOUT'] = '*.jar' elif '*.jar' not in env['LINKY_LAYOUT']: mx.warn("LINKY_LAYOUT already set") _mx_vm(['build'] + (args or []), config, env=env)
def _run_mx_suite_tests(): """ Mx suite specific tests. """ mx_javacompliance._test() if mx.is_windows(): def win(s, min_length=0): extra = min_length - len(s) if extra > 0: padding = 'X' * extra s += padding return s.replace('/', '\\') def _test(value, expect, open_fp): actual = mx._safe_path(value) if actual != expect: nl = os.linesep assert False, 'Failed safe_path test{} input: {} (len={}){}expect: {} (len={}){}actual: {} (len={})'.format(nl, value, len(value), nl, expect, len(expect), nl, actual, len(actual)) if open_fp and value != open_fp.name: try: with mx.open(value, 'w') as fp: fp.write('blah') with mx.open(value, 'r') as fp: contents = fp.read() assert contents == 'blah', contents finally: if os.path.exists(value): os.unlink(value) with tempfile.NamedTemporaryFile(prefix="safe_path_test", mode="w") as fp: cases = { win('C:/Home/mydir') : win('C:/Home/mydir'), win('C:/Home/mydir', 258) : win('C:/Home/mydir', 258), win('C:/Home/mydir', 259) : win('//?/') + win('C:/Home/mydir', 259), win('C:/Home/mydir', 260) : win('//?/') + win('C:/Home/mydir', 260), win('//Mac/Home/mydir') : win('//Mac/Home/mydir'), win('//Mac/Home/mydir', 258) : win('//Mac/Home/mydir', 258), win('//Mac/Home/mydir', 259) : win('//?/UNC/') + win('Mac/Home/mydir', 257), win('//Mac/Home/mydir', 260) : win('//?/UNC/') + win('Mac/Home/mydir', 258), win(fp.name) : win(fp.name), win(fp.name, 258) : win(fp.name, 258), win(fp.name, 259) : win('//?/') + win(fp.name, 259), win(fp.name, 260) : win('//?/') + win(fp.name, 260), } for value, expect in cases.items(): _test(value, expect, fp if value.startswith(fp.name) else None)
def build(self): super(GraalVmWatBuildTask, self).build() output_dir = self.subject.getOutputDir() for root, filename in self.subject.getProgramSources(): src = join( output_dir, mx_wasm.remove_extension(filename) + ".wasm") dst = join( root, mx_wasm.remove_extension(filename) + ".wasm") if mx.is_windows(): mx.copyfile(src, dst) else: os.symlink(src, dst)
def native_image_on_jvm(args, **kwargs): save_args = [] for arg in args: if arg == '--no-server' or arg.startswith('--server'): mx.warn('Ignoring server-mode native-image argument ' + arg) else: save_args.append(arg) _ensure_vm_built() if mx.is_windows(): config = graalvm_jvm_configs[-1] executable = vm_native_image_path(config) else: vm_link = join(svmbuild_dir(), 'vm') executable = join(vm_link, 'bin', 'native-image') if not exists(executable): mx.abort("Can not find " + executable + "\nDid you forget to build? Try `mx build`") mx.run([executable, '-H:CLibraryPath=' + clibrary_libpath()] + save_args, **kwargs)
def cflags(self): default_cflags = [] if mx.is_windows() and mx.get_jdk( tag=mx.DEFAULT_JDK_TAG).javaCompliance >= '11': default_cflags += ['-FS'] # necessary until GR-16572 is resolved if self._kind == self._kinds['shared_lib']: default_cflags += dict(windows=['-MD' ], ).get(mx.get_os(), ['-fPIC']) if mx.is_linux() or mx.is_darwin(): # Do not leak host paths via dwarf debuginfo def add_debug_prefix(prefix_dir): return '-fdebug-prefix-map={}={}'.format( prefix_dir, mx.basename(prefix_dir)) default_cflags += [add_debug_prefix(self.suite.vc_dir)] default_cflags += [add_debug_prefix(NinjaProject.get_jdk().home)] default_cflags += ['-gno-record-gcc-switches'] return default_cflags + super(DefaultNativeProject, self).cflags
jackpot = 'jackpot' def _espresso_gate_runner(args, tasks): # Jackpot configuration is inherited from Truffle. with Task('Jackpot', tasks, tags=[EspressoDefaultTags.jackpot]) as t: if t: jackpot(['--fail-on-warnings'], suite=None, nonZeroIsFatal=True) # REGISTER MX GATE RUNNER ######################### add_gate_runner(_suite, _espresso_gate_runner) if mx_sdk_vm.base_jdk_version() > 8: if mx.is_windows(): lib_espresso_cp = '%GRAALVM_HOME%\\lib\\graalvm\\lib-espresso.jar' else: lib_espresso_cp = '${GRAALVM_HOME}/lib/graalvm/lib-espresso.jar' else: if mx.is_windows(): lib_espresso_cp = '%GRAALVM_HOME%\\jre\\lib\\graalvm\\lib-espresso.jar' else: lib_espresso_cp = '${GRAALVM_HOME}/jre/lib/graalvm/lib-espresso.jar' mx_sdk_vm.register_graalvm_component( mx_sdk_vm.GraalVmLanguage( suite=_suite, name='Java on Truffle', short_name='java', installable_id='espresso',
license_files=[], third_party_license_files=[], dependencies=['sdk'], jar_distributions=['vm:INSTALLER', 'truffle:TruffleJSON'], support_distributions=['vm:INSTALLER_GRAALVM_SUPPORT'], launcher_configs=[ mx_sdk_vm.LauncherConfig( destination="bin/<exe:gu>", jar_distributions=['vm:INSTALLER', 'truffle:TruffleJSON'], dir_jars=True, main_class="org.graalvm.component.installer.ComponentInstaller", build_args=[], # Please see META-INF/native-image in the project for custom build options for native-image is_sdk_launcher=True, custom_launcher_script="mx.vm/gu.cmd" if mx.is_windows() else None, ), ], )) mx_sdk_vm.register_graalvm_component( mx_sdk_vm.GraalVmComponent( suite=_suite, name='GraalVM license files', short_name='gvm', dir_name='.', license_files=['LICENSE.txt'], third_party_license_files=['THIRD_PARTY_LICENSE.txt'], dependencies=[], support_distributions=['vm:VM_GRAALVM_SUPPORT'], ))
def jlink_new_jdk(jdk, dst_jdk_dir, module_dists, root_module_names=None, missing_export_target_action='create', with_source=lambda x: True): """ Uses jlink from `jdk` to create a new JDK image in `dst_jdk_dir` with `module_dists` and their dependencies added to the JDK image, replacing any existing modules of the same name. :param JDKConfig jdk: source JDK :param str dst_jdk_dir: path to use for the jlink --output option :param list module_dists: list of distributions defining modules :param list root_module_names: list of strings naming the module root set for the new JDK image. The named modules must either be in `module_dists` or in `jdk`. If None, then the root set will be all the modules in ``module_dists` and `jdk`. :param str missing_export_target_action: the action to perform for a qualifed export target that is not present in `module_dists` and does not have a hash stored in java.base. The choices are: "create" - an empty module is created "error" - raise an error None - do nothing :param lambda with_source: returns True if the sources of a module distribution must be included in the new JDK """ assert callable(with_source) if jdk.javaCompliance < '9': mx.abort('Cannot derive a new JDK from ' + jdk.home + ' with jlink since it is not JDK 9 or later') exploded_java_base_module = join(jdk.home, 'modules', 'java.base') if exists(exploded_java_base_module): mx.abort('Cannot derive a new JDK from ' + jdk.home + ' since it appears to be a developer build with exploded modules') jimage = join(jdk.home, 'lib', 'modules') jmods_dir = join(jdk.home, 'jmods') if not isfile(jimage): mx.abort('Cannot derive a new JDK from ' + jdk.home + ' since ' + jimage + ' is missing or is not an ordinary file') if not isdir(jmods_dir): mx.abort('Cannot derive a new JDK from ' + jdk.home + ' since ' + jmods_dir + ' is missing or is not a directory') jdk_modules = {jmd.name : jmd for jmd in jdk.get_modules()} modules = [as_java_module(dist, jdk) for dist in module_dists] all_module_names = frozenset(list(jdk_modules.keys()) + [m.name for m in modules]) # Read hashes stored in java.base (the only module in the JDK where hashes are stored) out = mx.LinesOutputCapture() mx.run([jdk.exe_path('jmod'), 'describe', jdk_modules['java.base'].get_jmod_path()], out=out) lines = out.lines hashes = {} for line in lines: if line.startswith('hashes'): parts = line.split() assert len(parts) == 4, 'expected hashes line to have 4 fields, got {} fields: {}'.format(len(parts), line) _, module_name, algorithm, hash_value = parts hashes[module_name] = (algorithm, hash_value) build_dir = mx.ensure_dir_exists(join(dst_jdk_dir + ".build")) try: # Handle targets of qualified exports that are not present in `modules` target_requires = {} for jmd in modules: for targets in jmd.exports.values(): for target in targets: if target not in all_module_names and target not in hashes: target_requires.setdefault(target, set()).add(jmd.name) if target_requires and missing_export_target_action is not None: if missing_export_target_action == 'error': mx.abort('Target(s) of qualified exports cannot be resolved: ' + '.'.join(target_requires.keys())) assert missing_export_target_action == 'create', 'invalid value for missing_export_target_action: ' + str(missing_export_target_action) extra_modules = [] for name, requires in target_requires.items(): module_jar = join(build_dir, name + '.jar') jmd = JavaModuleDescriptor(name, {}, requires={module : [] for module in requires}, uses=set(), provides={}, jarpath=module_jar) extra_modules.append(jmd) module_build_dir = mx.ensure_dir_exists(join(build_dir, name)) module_info_java = join(module_build_dir, 'module-info.java') module_info_class = join(module_build_dir, 'module-info.class') with open(module_info_java, 'w') as fp: print(jmd.as_module_info(), file=fp) mx.run([jdk.javac, '-d', module_build_dir, \ '--limit-modules=java.base,' + ','.join(jmd.requires.keys()), \ '--module-path=' + os.pathsep.join((m.jarpath for m in modules)), \ module_info_java]) with ZipFile(module_jar, 'w') as zf: zf.write(module_info_class, basename(module_info_class)) if exists(jmd.get_jmod_path()): os.remove(jmd.get_jmod_path()) mx.run([jdk.javac.replace('javac', 'jmod'), 'create', '--class-path=' + module_build_dir, jmd.get_jmod_path()]) modules.extend(extra_modules) all_module_names = frozenset(list(jdk_modules.keys()) + [m.name for m in modules]) # Extract src.zip from source JDK jdk_src_zip = join(jdk.home, 'lib', 'src.zip') dst_src_zip_contents = {} if isfile(jdk_src_zip): mx.logv('[Extracting ' + jdk_src_zip + ']') with ZipFile(jdk_src_zip, 'r') as zf: for name in zf.namelist(): if not name.endswith('/'): dst_src_zip_contents[name] = zf.read(name) else: mx.warn("'{}' does not exist or is not a file".format(jdk_src_zip)) for jmd in modules: # Remove existing sources for all the modules that we include dst_src_zip_contents = {key : dst_src_zip_contents[key] for key in dst_src_zip_contents if not key.startswith(jmd.name)} if with_source(jmd.dist): # Add the sources that we can share. # Extract module sources jmd_src_zip = jmd.jarpath[0:-len('.jar')] + '.src.zip' if isfile(jmd_src_zip): mx.logv('[Extracting ' + jmd_src_zip + ']') with ZipFile(jmd_src_zip, 'r') as zf: for name in zf.namelist(): if not name.endswith('/'): dst_src_zip_contents[jmd.name + '/' + name] = zf.read(name) # Add module-info.java to sources dst_src_zip_contents[jmd.name + '/module-info.java'] = jmd.as_module_info(extras_as_comments=False) # Now build the new JDK image with jlink jlink = [jdk.javac.replace('javac', 'jlink')] if jdk_enables_jvmci_by_default(jdk): # On JDK 9+, +EnableJVMCI forces jdk.internal.vm.ci to be in the root set jlink.append('-J-XX:-EnableJVMCI') if root_module_names is not None: missing = frozenset(root_module_names) - all_module_names if missing: mx.abort('Invalid module(s): {}.\nAvailable modules: {}'.format(','.join(missing), ','.join(sorted(all_module_names)))) jlink.append('--add-modules=' + ','.join(root_module_names)) else: jlink.append('--add-modules=' + ','.join(sorted(all_module_names))) module_path = jmods_dir if modules: module_path = os.pathsep.join((m.get_jmod_path(respect_stripping=True) for m in modules)) + os.pathsep + module_path jlink.append('--module-path=' + module_path) jlink.append('--output=' + dst_jdk_dir) # These options are inspired by how OpenJDK runs jlink to produce the final runtime image. jlink.extend(['-J-XX:+UseSerialGC', '-J-Xms32M', '-J-Xmx512M', '-J-XX:TieredStopAtLevel=1']) jlink.append('-J-Dlink.debug=true') jlink.append('--dedup-legal-notices=error-if-not-same-content') jlink.append('--keep-packaged-modules=' + join(dst_jdk_dir, 'jmods')) # TODO: investigate the options below used by OpenJDK to see if they should be used: # --release-info: this allow extra properties to be written to the <jdk>/release file # --order-resources: specifies order of resources in generated lib/modules file. # This is apparently not so important if a CDS archive is available. # --generate-jli-classes: pre-generates a set of java.lang.invoke classes. # See https://github.com/openjdk/jdk/blob/master/make/GenerateLinkOptData.gmk mx.logv('[Creating JDK image]') mx.run(jlink) dst_src_zip = join(dst_jdk_dir, 'lib', 'src.zip') mx.logv('[Creating ' + dst_src_zip + ']') with ZipFile(dst_src_zip, 'w', compression=ZIP_DEFLATED, allowZip64=True) as zf: for name, contents in sorted(dst_src_zip_contents.items()): zf.writestr(name, contents) mx.logv('[Copying static libraries]') lib_prefix = mx.add_lib_prefix('') lib_suffix = '.lib' if mx.is_windows() else '.a' lib_directory = join(jdk.home, 'lib') dst_lib_directory = join(dst_jdk_dir, 'lib') for f in os.listdir(lib_directory): if f.startswith(lib_prefix) and f.endswith(lib_suffix): lib_path = join(lib_directory, f) if isfile(lib_path): shutil.copy2(lib_path, dst_lib_directory) # Build the list of modules whose classes might have annotations # to be processed by native-image (GR-15192). with open(join(dst_jdk_dir, 'lib', 'native-image-modules.list'), 'w') as fp: print('# Modules whose classes might have annotations processed by native-image', file=fp) for m in modules: print(m.name, file=fp) finally: if not mx.get_opts().verbose: # Preserve build directory so that javac command can be re-executed # by cutting and pasting verbose output. shutil.rmtree(build_dir) # Create CDS archive (https://openjdk.java.net/jeps/341). out = mx.OutputCapture() mx.logv('[Creating CDS shared archive]') if mx.run([mx.exe_suffix(join(dst_jdk_dir, 'bin', 'java')), '-Xshare:dump', '-Xmx128M', '-Xms128M'], out=out, err=out, nonZeroIsFatal=False) != 0: mx.log(out.data) mx.abort('Error generating CDS shared archive')
def config_entry(key, value): value_substitute = mx_subst.path_substitutions.substitute(value) if mx.is_windows(): # cmake does not like backslashes value_substitute = value_substitute.replace("\\", "/") return '-D{}={}'.format(key, value_substitute)
def _netbeansinit_project(p, jdks=None, files=None, libFiles=None, dists=None): dists = [] if dists is None else dists nb_dir = mx.ensure_dir_exists(join(p.dir)) nbproject_dir = mx.ensure_dir_exists(join(nb_dir, 'nbproject')) jdk = mx.get_jdk(p.javaCompliance) assert jdk if jdks is not None: jdks.add(jdk) execDir = mx.primary_suite().dir out = mx.XMLDoc() out.open('project', {'name' : p.name, 'default' : 'default', 'basedir' : '.'}) out.element('description', data='Builds, tests, and runs the project ' + p.name + '.') out.element('available', {'file' : 'nbproject/build-impl.xml', 'property' : 'build.impl.exists'}) out.element('import', {'file' : 'nbproject/build-impl.xml', 'optional' : 'true'}) out.element('extension-point', {'name' : '-mx-init'}) out.element('available', {'file' : 'nbproject/build-impl.xml', 'property' : 'mx.init.targets', 'value' : 'init'}) out.element('property', {'name' : 'mx.init.targets', 'value' : ''}) out.element('bindtargets', {'extensionPoint' : '-mx-init', 'targets' : '${mx.init.targets}'}) out.open('target', {'name' : '-post-init'}) out.open('pathconvert', {'property' : 'comma.javac.classpath', 'pathsep' : ','}) out.element('path', {'path' : '${javac.classpath}'}) out.close('pathconvert') out.open('restrict', {'id' : 'missing.javac.classpath'}) out.element('filelist', {'dir' : '${basedir}', 'files' : '${comma.javac.classpath}'}) out.open('not') out.element('exists') out.close('not') out.close('restrict') out.element('property', {'name' : 'missing.javac.classpath', 'refid' : 'missing.javac.classpath'}) out.open('condition', {'property' : 'no.dependencies', 'value' : 'true'}) out.element('equals', {'arg1' : '${missing.javac.classpath}', 'arg2' : ''}) out.close('condition') out.element('property', {'name' : 'no.dependencies', 'value' : 'false'}) out.open('condition', {'property' : 'no.deps'}) out.element('equals', {'arg1' : '${no.dependencies}', 'arg2' : 'true'}) out.close('condition') out.close('target') out.open('target', {'name' : 'clean'}) out.open('exec', {'executable' : sys.executable, 'failonerror' : 'true', 'dir' : execDir}) out.element('env', {'key' : 'JAVA_HOME', 'value' : jdk.home}) out.element('arg', {'value' : os.path.abspath(__file__)}) out.element('arg', {'value' : 'clean'}) out.element('arg', {'value' : '--projects'}) out.element('arg', {'value' : p.name}) out.close('exec') out.close('target') out.open('target', {'name' : 'compile'}) out.open('exec', {'executable' : sys.executable, 'failonerror' : 'true', 'dir' : execDir}) out.element('env', {'key' : 'JAVA_HOME', 'value' : jdk.home}) out.element('arg', {'value' : os.path.abspath(__file__)}) out.element('arg', {'value' : 'build'}) dependsOn = p.name for d in dists: dependsOn = dependsOn + ',' + d.name out.element('arg', {'value' : '--only'}) out.element('arg', {'value' : dependsOn}) out.element('arg', {'value' : '--force-javac'}) out.element('arg', {'value' : '--no-native'}) out.element('arg', {'value' : '--no-daemon'}) out.close('exec') out.close('target') out.open('target', {'name' : 'package', 'if' : 'build.impl.exists'}) out.element('antcall', {'target': '-package', 'inheritall': 'true', 'inheritrefs': 'true'}) out.close('target') out.open('target', {'name' : '-package', 'depends' : '-mx-init'}) out.element('loadfile', {'srcFile' : join(p.suite.get_output_root(), 'netbeans.log'), 'property' : 'netbeans.log', 'failonerror' : 'false'}) out.element('echo', {'message' : '...truncated...${line.separator}', 'output' : join(p.suite.get_output_root(), 'netbeans.log')}) out.element('echo', {'message' : '${netbeans.log}'}) for d in dists: if d.isDistribution(): out.element('touch', {'file' : '${java.io.tmpdir}/' + d.name}) out.element('echo', {'message' : d.name + ' set to now${line.separator}', 'append' : 'true', 'output' : join(p.suite.get_output_root(), 'netbeans.log')}) out.open('copy', {'todir' : '${build.classes.dir}', 'overwrite' : 'true'}) out.element('resources', {'refid' : 'changed.files'}) out.close('copy') if len(p.annotation_processors()) > 0: out.open('copy', {'todir' : '${src.ap-source-output.dir}'}) out.open('fileset', {'dir': '${cos.src.dir.internal}/../sources/'}) out.element('include', {'name': '**/*.java'}) out.close('fileset') out.close('copy') out.open('exec', {'executable' : '${ant.home}/bin/ant', 'spawn' : 'true'}) out.element('arg', {'value' : '-f'}) out.element('arg', {'value' : '${ant.file}'}) out.element('arg', {'value' : 'packagelater'}) out.close('exec') out.close('target') for d in dists: if d.isDistribution(): out.open('target', {'name' : 'checkpackage-' + d.name}) out.open('tstamp') out.element('format', {'pattern' : 'S', 'unit' : 'millisecond', 'property' : 'at.' + d.name}) out.close('tstamp') out.element('touch', {'file' : '${java.io.tmpdir}/' + d.name, 'millis' : '${at.' + d.name + '}0000'}) out.element('echo', {'message' : d.name + ' touched to ${at.' + d.name + '}0000${line.separator}', 'append' : 'true', 'output' : join(p.suite.get_output_root(), 'netbeans.log')}) out.element('sleep', {'seconds' : '3'}) out.open('condition', {'property' : 'mx.' + d.name, 'value' : sys.executable}) out.open('islastmodified', {'millis' : '${at.' + d.name + '}0000', 'mode' : 'equals'}) out.element('file', {'file' : '${java.io.tmpdir}/' + d.name}) out.close('islastmodified') out.close('condition') out.element('echo', {'message' : d.name + ' defined as ' + '${mx.' + d.name + '}${line.separator}', 'append' : 'true', 'output' : join(p.suite.get_output_root(), 'netbeans.log')}) out.close('target') out.open('target', {'name' : 'packagelater-' + d.name, 'depends' : 'checkpackage-' + d.name, 'if' : 'mx.' + d.name}) out.open('exec', {'executable' : '${mx.' + d.name + '}', 'failonerror' : 'true', 'dir' : execDir, 'output' : join(p.suite.get_output_root(), 'netbeans.log'), 'append' : 'true'}) out.element('env', {'key' : 'JAVA_HOME', 'value' : jdk.home}) out.element('arg', {'value' : os.path.abspath(__file__)}) out.element('arg', {'value' : 'build'}) out.element('arg', {'value' : '-f'}) out.element('arg', {'value' : '--only'}) out.element('arg', {'value' : d.name}) out.element('arg', {'value' : '--force-javac'}) out.element('arg', {'value' : '--no-native'}) out.element('arg', {'value' : '--no-daemon'}) out.close('exec') out.close('target') dependsOn = '' sep = '' for d in dists: dependsOn = dependsOn + sep + 'packagelater-' + d.name sep = ',' out.open('target', {'name' : 'packagelater', 'depends' : dependsOn}) out.close('target') out.open('target', {'name' : 'jar', 'depends' : 'compile'}) out.close('target') out.element('target', {'name' : 'test', 'depends' : 'run'}) out.element('target', {'name' : 'test-single', 'depends' : 'run'}) out.open('target', {'name' : 'run'}) out.element('property', {'name' : 'test.class', 'value' : p.name}) out.open('exec', {'executable' : sys.executable, 'failonerror' : 'true', 'dir' : execDir}) out.element('env', {'key' : 'JAVA_HOME', 'value' : jdk.home}) out.element('arg', {'value' : os.path.abspath(__file__)}) out.element('arg', {'value' : 'unittest'}) out.element('arg', {'value' : '${test.class}'}) out.close('exec') out.close('target') out.element('target', {'name' : 'debug-test', 'depends' : 'debug'}) out.open('target', {'name' : 'debug', 'depends' : '-mx-init'}) out.element('property', {'name' : 'test.class', 'value' : p.name}) out.open('nbjpdastart', {'addressproperty' : 'jpda.address', 'name' : p.name}) out.open('classpath') out.open('fileset', {'dir' : '..'}) out.element('include', {'name' : '*/bin/'}) out.close('fileset') out.close('classpath') out.open('sourcepath') out.element('pathelement', {'location' : 'src'}) out.close('sourcepath') out.close('nbjpdastart') out.open('exec', {'executable' : sys.executable, 'failonerror' : 'true', 'dir' : execDir}) out.element('env', {'key' : 'JAVA_HOME', 'value' : jdk.home}) out.element('arg', {'value' : os.path.abspath(__file__)}) out.element('arg', {'value' : '-d'}) out.element('arg', {'value' : '--attach'}) out.element('arg', {'value' : '${jpda.address}'}) out.element('arg', {'value' : 'unittest'}) out.element('arg', {'value' : '${test.class}'}) out.close('exec') out.close('target') out.open('target', {'name' : 'javadoc'}) out.open('exec', {'executable' : sys.executable, 'failonerror' : 'true', 'dir' : execDir}) out.element('env', {'key' : 'JAVA_HOME', 'value' : jdk.home}) out.element('arg', {'value' : os.path.abspath(__file__)}) out.element('arg', {'value' : 'javadoc'}) out.element('arg', {'value' : '--projects'}) out.element('arg', {'value' : p.name}) out.element('arg', {'value' : '--force'}) out.close('exec') out.element('nbbrowse', {'file' : 'javadoc/index.html'}) out.close('target') out.close('project') mx.update_file(join(nb_dir, 'build.xml'), out.xml(indent='\t', newl='\n')) if files is not None: files.append(join(nb_dir, 'build.xml')) out = mx.XMLDoc() out.open('project', {'xmlns' : 'http://www.netbeans.org/ns/project/1'}) out.element('type', data='org.netbeans.modules.java.j2seproject') out.open('configuration') out.open('data', {'xmlns' : 'http://www.netbeans.org/ns/j2se-project/3'}) out.element('name', data=p.name) out.element('explicit-platform', {'explicit-source-supported' : 'true'}) out.open('source-roots') out.element('root', {'id' : 'src.dir'}) if len(p.annotation_processors()) > 0: out.element('root', {'id' : 'src.ap-source-output.dir', 'name' : 'Generated Packages'}) out.close('source-roots') out.open('test-roots') out.close('test-roots') out.close('data') firstDep = [] def processDep(dep, edge): if dep is p: return if dep.isProject(): n = dep.name.replace('.', '_') if not firstDep: out.open('references', {'xmlns' : 'http://www.netbeans.org/ns/ant-project-references/1'}) firstDep.append(dep) out.open('reference') out.element('foreign-project', data=n) out.element('artifact-type', data='jar') out.element('script', data='build.xml') out.element('target', data='jar') out.element('clean-target', data='clean') out.element('id', data='jar') out.close('reference') #pylint: disable=too-many-function-args p.walk_deps(visit=processDep, ignoredEdges=[mx.DEP_EXCLUDED]) if firstDep: out.close('references') out.close('configuration') out.close('project') mx.update_file(join(nbproject_dir, 'project.xml'), out.xml(indent=' ', newl='\n')) if files is not None: files.append(join(nbproject_dir, 'project.xml')) out = StringIO() jdkPlatform = 'JDK_' + str(jdk.version) annotationProcessorEnabled = "false" annotationProcessorSrcFolder = "" annotationProcessorSrcFolderRef = "" if len(p.annotation_processors()) > 0: annotationProcessorEnabled = "true" mx.ensure_dir_exists(p.source_gen_dir()) annotationProcessorSrcFolder = os.path.relpath(p.source_gen_dir(), nb_dir) annotationProcessorSrcFolder = annotationProcessorSrcFolder.replace('\\', '\\\\') annotationProcessorSrcFolderRef = "src.ap-source-output.dir=" + annotationProcessorSrcFolder canSymlink = not (mx.is_windows() or mx.is_cygwin()) and 'symlink' in dir(os) if canSymlink: nbBuildDir = join(nbproject_dir, 'build') apSourceOutRef = "annotation.processing.source.output=" + annotationProcessorSrcFolder if os.path.lexists(nbBuildDir): os.unlink(nbBuildDir) os.symlink(p.output_dir(), nbBuildDir) else: nbBuildDir = p.output_dir() apSourceOutRef = "" mx.ensure_dir_exists(p.output_dir()) mx_ide_eclipse._copy_eclipse_settings(nb_dir, p) content = """ annotation.processing.enabled=""" + annotationProcessorEnabled + """ annotation.processing.enabled.in.editor=""" + annotationProcessorEnabled + """ """ + apSourceOutRef + """ annotation.processing.processors.list= annotation.processing.run.all.processors=true application.title=""" + p.name + """ application.vendor=mx auxiliary.de-markiewb-netbeans-plugins-eclipse-formatter.eclipseFormatterActiveProfile= auxiliary.de-markiewb-netbeans-plugins-eclipse-formatter.eclipseFormatterEnabled=true auxiliary.de-markiewb-netbeans-plugins-eclipse-formatter.eclipseFormatterLocation= auxiliary.de-markiewb-netbeans-plugins-eclipse-formatter.enableFormatAsSaveAction=true auxiliary.de-markiewb-netbeans-plugins-eclipse-formatter.linefeed= auxiliary.de-markiewb-netbeans-plugins-eclipse-formatter.preserveBreakPoints=true auxiliary.de-markiewb-netbeans-plugins-eclipse-formatter.SaveActionModifiedLinesOnly=false auxiliary.de-markiewb-netbeans-plugins-eclipse-formatter.showNotifications=false auxiliary.de-markiewb-netbeans-plugins-eclipse-formatter.sourcelevel= auxiliary.de-markiewb-netbeans-plugins-eclipse-formatter.useProjectPref=true auxiliary.de-markiewb-netbeans-plugins-eclipse-formatter.useProjectSettings=true auxiliary.de-markiewb-netbeans-plugins-eclipse-formatter.eclipseFormatterActiveProfile= auxiliary.org-netbeans-spi-editor-hints-projects.perProjectHintSettingsEnabled=true auxiliary.org-netbeans-spi-editor-hints-projects.perProjectHintSettingsFile=nbproject/cfg_hints.xml build.classes.dir=${build.dir} build.classes.excludes=**/*.java,**/*.form # This directory is removed when the project is cleaned: build.dir=""" + nbBuildDir + """ $cos.update=package $cos.update.resources=changed.files compile.on.save=true build.generated.sources.dir=${build.dir}/generated-sources # Only compile against the classpath explicitly listed here: build.sysclasspath=ignore build.test.classes.dir=${build.dir}/test/classes build.test.results.dir=${build.dir}/test/results # Uncomment to specify the preferred debugger connection transport: #debug.transport=dt_socket debug.classpath=\\ ${run.classpath} debug.test.classpath=\\ ${run.test.classpath} # This directory is removed when the project is cleaned: dist.dir=dist dist.jar=${dist.dir}/""" + p.name + """.jar dist.javadoc.dir=${dist.dir}/javadoc endorsed.classpath= excludes= includes=** jar.compress=false java.main.action=test # Space-separated list of extra javac options javac.compilerargs=-XDignore.symbol.file javac.deprecation=false javac.source=""" + str(p.javaCompliance) + """ javac.target=""" + str(p.javaCompliance) + """ javac.test.classpath=\\ ${javac.classpath}:\\ ${build.classes.dir} javadoc.additionalparam= javadoc.author=false javadoc.encoding=${source.encoding} javadoc.noindex=false javadoc.nonavbar=false javadoc.notree=false javadoc.private=false javadoc.splitindex=true javadoc.use=true javadoc.version=false javadoc.windowtitle= manifest.file=manifest.mf meta.inf.dir=${src.dir}/META-INF mkdist.disabled=false platforms.""" + jdkPlatform + """.home=""" + jdk.home + """ platform.active=""" + jdkPlatform + """ run.classpath=\\ ${javac.classpath}:\\ ${build.classes.dir} # Space-separated list of JVM arguments used when running the project # (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value # or test-sys-prop.name=value to set system properties for unit tests): run.jvmargs= run.test.classpath=\\ ${javac.test.classpath}:\\ ${build.test.classes.dir} test.src.dir=./test """ + annotationProcessorSrcFolderRef + """ source.encoding=UTF-8""".replace(':', os.pathsep).replace('/', os.sep) print(content, file=out) # Workaround for NetBeans "too clever" behavior. If you want to be # able to press F6 or Ctrl-F5 in NetBeans and run/debug unit tests # then the project must have its main.class property set to an # existing class with a properly defined main method. Until this # behavior is remedied, we specify a well known Truffle class # that will be on the class path for most Truffle projects. # This can be overridden by defining a netbeans.project.properties # attribute for a project in suite.py (see below). print("main.class=com.oracle.truffle.api.impl.Accessor", file=out) # Add extra properties specified in suite.py for this project if hasattr(p, 'netbeans.project.properties'): properties = getattr(p, 'netbeans.project.properties') for prop in [properties] if isinstance(properties, str) else properties: print(prop, file=out) mainSrc = True for src in p.srcDirs: srcDir = mx.ensure_dir_exists(join(p.dir, src)) ref = 'file.reference.' + p.name + '-' + src print(ref + '=' + os.path.relpath(srcDir, nb_dir), file=out) if mainSrc: print('src.dir=${' + ref + '}', file=out) mainSrc = False else: print('src.' + src + '.dir=${' + ref + '}', file=out) javacClasspath = [] def newDepsCollector(into): return lambda dep, edge: into.append(dep) if dep.isLibrary() or dep.isJdkLibrary() or dep.isProject() or dep.isClasspathDependency() else None deps = [] p.walk_deps(visit=newDepsCollector(deps)) annotationProcessorOnlyDeps = [] if len(p.annotation_processors()) > 0: for apDep in p.annotation_processors(): resolvedApDeps = [] apDep.walk_deps(visit=newDepsCollector(resolvedApDeps)) for resolvedApDep in resolvedApDeps: if not resolvedApDep in deps: deps.append(resolvedApDep) annotationProcessorOnlyDeps.append(resolvedApDep) annotationProcessorReferences = [] for dep in deps: if dep == p: continue if dep.isLibrary() or dep.isJdkLibrary(): if dep.isLibrary(): path = dep.get_path(resolve=True) sourcePath = dep.get_source_path(resolve=True) else: path = dep.classpath_repr(jdk, resolve=True) sourcePath = dep.get_source_path(jdk) if path: if os.sep == '\\': path = path.replace('\\', '\\\\') ref = 'file.reference.' + dep.name + '-bin' print(ref + '=' + path, file=out) if libFiles: libFiles.append(path) if sourcePath: if os.sep == '\\': sourcePath = sourcePath.replace('\\', '\\\\') print('source.reference.' + dep.name + '-bin=' + sourcePath, file=out) elif dep.isMavenProject(): path = dep.get_path(resolve=False) if path: if os.sep == '\\': path = path.replace('\\', '\\\\') ref = 'file.reference.' + dep.name + '-bin' print(ref + '=' + path, file=out) elif dep.isProject(): n = dep.name.replace('.', '_') relDepPath = os.path.relpath(dep.dir, nb_dir).replace(os.sep, '/') if canSymlink: depBuildPath = join('nbproject', 'build') else: depBuildPath = 'dist/' + dep.name + '.jar' ref = 'reference.' + n + '.jar' print('project.' + n + '=' + relDepPath, file=out) print(ref + '=${project.' + n + '}/' + depBuildPath, file=out) elif dep.isJreLibrary(): continue elif dep.isClasspathDependency(): extra = [di for di in dep.deps if di not in deps] if dep.isDistribution() and dep.deps and not extra: # ignore distribution classpath dependencies that only contain other explicit depedencies continue path = dep.classpath_repr(resolve=True) sourcePath = dep.get_source_path(jdk) if hasattr(dep, 'get_source_path') else None if path: if os.sep == '\\': path = path.replace('\\', '\\\\') ref = 'file.reference.' + dep.name + '-bin' print(ref + '=' + path, file=out) if libFiles: libFiles.append(path) if sourcePath: if os.sep == '\\': sourcePath = sourcePath.replace('\\', '\\\\') print('source.reference.' + dep.name + '-bin=' + sourcePath, file=out) if not dep in annotationProcessorOnlyDeps: javacClasspath.append('${' + ref + '}') else: annotationProcessorReferences.append('${' + ref + '}') print('javac.classpath=\\\n ' + (os.pathsep + '\\\n ').join(javacClasspath), file=out) print('javac.processorpath=' + (os.pathsep + '\\\n ').join(['${javac.classpath}'] + annotationProcessorReferences), file=out) print('javac.test.processorpath=' + (os.pathsep + '\\\n ').join(['${javac.test.classpath}'] + annotationProcessorReferences), file=out) mx.update_file(join(nbproject_dir, 'project.properties'), out.getvalue()) out.close() if files is not None: files.append(join(nbproject_dir, 'project.properties')) for source in p.suite.netbeans_settings_sources().get('cfg_hints.xml'): with open(source) as fp: content = fp.read() mx.update_file(join(nbproject_dir, 'cfg_hints.xml'), content) if files is not None: files.append(join(p.dir, 'nbproject', 'cfg_hints.xml'))
dir_name='installer', license_files=[], third_party_license_files=[], dependencies=[], jar_distributions=['vm:INSTALLER'], support_distributions=['vm:INSTALLER_GRAALVM_SUPPORT'], launcher_configs=[ mx_sdk_vm.LauncherConfig( destination="bin/<exe:gu>", jar_distributions=[], dir_jars=True, main_class="org.graalvm.component.installer.ComponentInstaller", build_args=[], # Please see META-INF/native-image in the project for custom build options for native-image is_sdk_launcher=True, custom_bash_launcher="mx.vm/gu" if mx.is_windows() else None, ), ], )) mx_sdk_vm.register_graalvm_component( mx_sdk_vm.GraalVmComponent( suite=_suite, name='GraalVM license files', short_name='gvm', dir_name='.', license_files=['LICENSE.txt'], third_party_license_files=['3rd_party_licenses.txt'], dependencies=[], support_distributions=['vm:VM_GRAALVM_SUPPORT'], ))
class DefaultNativeProject(NinjaProject): """A NinjaProject that makes many assumptions when generating a build manifest. It is assumed that: #. Directory layout is fixed: - `include` is a flat subdir containing public headers, and - `src` subdir contains sources and private headers. #. There is only one deliverable: - Kind is the value of the `native` attribute, and - Name is the value of the `deliverable` attribute if it is specified, otherwise it is derived from the `name` of the project. #. All source files are supported and necessary to build the deliverable. #. All `include_dirs` and `libs` provided by build dependencies are necessary to build the deliverable. #. The deliverable and the public headers are intended for distribution. Attributes native : {'static_lib', 'shared_lib'} Kind of the deliverable. Depending on the value, the necessary flags will be prepended to `cflags` and `ldflags` automatically. deliverable : str, optional Name of the deliverable. By default, it is derived from the `name` of the project. """ include = 'include' src = 'src' _kinds = dict( static_lib=dict(target=lambda name: mx.add_lib_prefix(name) + ('.lib' if mx.is_windows() else '.a'), ), shared_lib=dict( target=lambda name: mx.add_lib_suffix(mx.add_lib_prefix(name)), ), executable=dict(target=mx.exe_suffix, ), ) def __init__(self, suite, name, subDir, srcDirs, deps, workingSets, d, kind, **kwargs): self.deliverable = kwargs.pop('deliverable', name.split('.')[-1]) if srcDirs: mx.abort( '"sourceDirs" is not supported for default native projects') srcDirs += [self.include, self.src] super(DefaultNativeProject, self).__init__(suite, name, subDir, srcDirs, deps, workingSets, d, **kwargs) try: self._kind = self._kinds[kind] except KeyError: mx.abort('"native" should be one of {}, but "{}" is given'.format( list(self._kinds.keys()), kind)) include_dir = mx.join(self.dir, self.include) if next(os.walk(include_dir))[1]: mx.abort('include directory must have a flat structure') self.include_dirs = [include_dir] if kind == 'static_lib': self.libs = [mx.join(self.out_dir, mx.get_arch(), self._target)] @property def _target(self): return self._kind['target'](self.deliverable) @property def cflags(self): default_cflags = [] if self._kind == self._kinds['shared_lib']: default_cflags += dict(windows=['-MD' ], ).get(mx.get_os(), ['-fPIC']) if mx.is_linux() or mx.is_darwin(): # Do not leak host paths via dwarf debuginfo def add_debug_prefix(prefix_dir): return '-fdebug-prefix-map={}={}'.format( prefix_dir, mx.basename(prefix_dir)) default_cflags += [add_debug_prefix(self.suite.vc_dir)] default_cflags += [add_debug_prefix(NinjaProject.get_jdk().home)] default_cflags += ['-gno-record-gcc-switches'] return default_cflags + super(DefaultNativeProject, self).cflags @property def ldflags(self): default_ldflags = [] if self._kind == self._kinds['shared_lib']: default_ldflags += dict( darwin=['-dynamiclib', '-undefined', 'dynamic_lookup'], windows=['-dll'], ).get(mx.get_os(), ['-shared', '-fPIC']) return default_ldflags + super(DefaultNativeProject, self).ldflags @property def h_files(self): return self._source['files'].get('.h', []) @property def c_files(self): return self._source['files'].get('.c', []) @property def cxx_files(self): return self._source['files'].get('.cc', []) @property def asm_sources(self): return self._source['files'].get('.S', []) def generate_manifest(self, path): unsupported_source_files = list( set(self._source['files'].keys()) - {'.h', '.c', '.cc', '.S'}) if unsupported_source_files: mx.abort( '{} source files are not supported by default native projects'. format(unsupported_source_files)) with NinjaManifestGenerator(self, open(path, 'w')) as gen: gen.comment('Project rules') cc = cxx = asm = None if self.c_files: cc = gen.cc_rule() if self.cxx_files: cxx = gen.cc_rule(cxx=True) if self.asm_sources: asm = gen.asm_rule() if mx.is_windows( ) else cc if cc else gen.cc_rule() ar = link = None if self._kind == self._kinds['static_lib']: ar = gen.ar_rule() else: link = gen.link_rule(cxx=bool(self.cxx_files)) gen.variables( cflags=[ mx_subst.path_substitutions.substitute(cflag) for cflag in self.cflags ], ldflags=[ mx_subst.path_substitutions.substitute(ldflag) for ldflag in self.ldflags ] if link else None, ldlibs=self.ldlibs if link else None, ) gen.include( collections.OrderedDict.fromkeys( # remove the duplicates while maintaining the ordering [mx.dirname(h_file) for h_file in self.h_files] + list( itertools.chain.from_iterable( getattr(d, 'include_dirs', []) for d in self.buildDependencies))).keys()) gen.comment('Compiled project sources') object_files = [cc(f) for f in self.c_files] gen.newline() object_files += [cxx(f) for f in self.cxx_files] gen.newline() object_files += [asm(f) for f in self.asm_sources] gen.newline() gen.comment('Project deliverable') if self._kind == self._kinds['static_lib']: ar(self._target, object_files) else: link( self._target, object_files + list( itertools.chain.from_iterable( getattr(d, 'libs', []) for d in self.buildDependencies))) def _archivable_results(self, target_arch, use_relpath, single): def result(base_dir, file_path): assert not mx.isabs(file_path) archive_path = file_path if use_relpath else mx.basename(file_path) return mx.join(base_dir, file_path), archive_path yield result(mx.join(self.out_dir, target_arch), self._target) if not single: for header in os.listdir(mx.join(self.dir, self.include)): yield result(self.dir, mx.join(self.include, header))
], support_distributions=['vm:INSTALLER_GRAALVM_SUPPORT'], launcher_configs=[ mx_sdk_vm.LauncherConfig( destination="bin/<exe:gu>", jar_distributions=[ 'vm:INSTALLER', 'truffle:TruffleJSON' ], dir_jars=True, main_class="org.graalvm.component.installer.ComponentInstaller", link_at_build_time=False, build_args=gu_build_args, # Please see META-INF/native-image in the project for custom build options for native-image is_sdk_launcher=True, custom_launcher_script="mx.vm/gu.cmd" if mx.is_windows() else None, ), ], stability="supported", )) mx_sdk_vm.register_graalvm_component(mx_sdk_vm.GraalVmComponent( suite=_suite, name='GraalVM license files', short_name='gvm', dir_name='.', license_files=['LICENSE.txt'], third_party_license_files=['THIRD_PARTY_LICENSE.txt'], dependencies=[], support_distributions=['vm:VM_GRAALVM_SUPPORT'],
def quote(path): return '"{}"'.format(path) if mx.is_windows() and ( ' ' in path or ('$project' in path and ' ' in self.project.dir)) else path
def build(source_file): output = os.path.splitext(source_file)[0] + ( '.obj' if mx.is_windows() else '.o') return self.n.build(output, rule, self._resolve(source_file))[0]