Skip to main content
Glama
kotlincd_jar_creator.bzl23.7 kB
# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under both the MIT license found in the # LICENSE-MIT file in the root directory of this source tree and the Apache # License, Version 2.0 found in the LICENSE-APACHE file in the root directory # of this source tree. load( "@prelude//java:java_providers.bzl", "ClasspathSnapshotGranularity", "JavaClasspathEntry", # @unused Used as a type "JavaCompileOutputs", # @unused Used as a type "JavaCompilingDepsTSet", # @unused Used as a type "JavaLibraryInfo", "generate_java_classpath_snapshot", "make_compile_outputs", ) load("@prelude//java:java_resources.bzl", "get_resources_map") load("@prelude//java:java_toolchain.bzl", "AbiGenerationMode", "DepFiles", "JavaToolchainInfo") load( "@prelude//java/plugins:java_annotation_processor.bzl", "AnnotationProcessorProperties", # @unused Used as type ) load( "@prelude//java/plugins:java_plugin.bzl", "PluginParams", # @unused Used as type ) load( "@prelude//java/utils:java_utils.bzl", "CustomJdkInfo", # @unused Used as type ) load( "@prelude//jvm:cd_jar_creator_util.bzl", "BuildMode", "OutputPaths", "TargetType", "base_qualified_name", "declare_prefixed_output", "define_output_paths", "encode_command", "generate_abi_jars", "get_compiling_deps_tset", "prepare_cd_exe", "prepare_final_jar", "setup_dep_files", ) load("@prelude//kotlin:kotlin_toolchain.bzl", "KotlinToolchainInfo") load("@prelude//kotlin:kotlin_utils.bzl", "get_kotlinc_compatible_target") load("@prelude//utils:expect.bzl", "expect") load("@prelude//utils:utils.bzl", "map_idx") def create_jar_artifact_kotlincd( actions: AnalysisActions, actions_identifier: [str, None], abi_generation_mode: [AbiGenerationMode, None], java_toolchain: JavaToolchainInfo, kotlin_toolchain: KotlinToolchainInfo, javac_tool: [str, RunInfo, Artifact, None], label: Label, srcs: list[Artifact], remove_classes: list[str], resources: list[Artifact], resources_root: [str, None], annotation_processor_properties: AnnotationProcessorProperties, plugin_params: [PluginParams, None], manifest_file: Artifact | None, source_level: int, target_level: int, deps: list[Dependency], required_for_source_only_abi: bool, source_only_abi_deps: list[Dependency], extra_arguments: cmd_args, additional_classpath_entries: JavaCompilingDepsTSet | None, bootclasspath_entries: list[Artifact], custom_jdk_info: CustomJdkInfo | None, is_building_android_binary: bool, friend_paths: list[Dependency], kotlin_compiler_plugins: dict, extra_kotlinc_arguments: list, incremental: bool, incremental_qe_applied: bool, enable_used_classes: bool, language_version: str, is_creating_subtarget: bool = False, optional_dirs: list[OutputArtifact] = [], jar_postprocessor: [RunInfo, None] = None, debug_port: [int, None] = None) -> (JavaCompileOutputs, Artifact): resources_map = get_resources_map( java_toolchain = java_toolchain, package = label.package, resources = resources, resources_root = resources_root, ) expect(abi_generation_mode != AbiGenerationMode("source"), "abi_generation_mode: source is not supported in kotlincd") actual_abi_generation_mode = abi_generation_mode or AbiGenerationMode("class") if srcs else AbiGenerationMode("none") output_paths = define_output_paths(actions, actions_identifier, label) should_create_class_abi = \ not is_creating_subtarget and \ (actual_abi_generation_mode == AbiGenerationMode("class") or not is_building_android_binary) and \ kotlin_toolchain.jvm_abi_gen_plugin != None if should_create_class_abi: class_abi_jar = declare_prefixed_output(actions, actions_identifier, "class-abi.jar") class_abi_output_dir = declare_prefixed_output(actions, actions_identifier, "class_abi_dir", dir = True) jvm_abi_gen = cmd_args(output_paths.jar.as_output(), format = "{}/jvm-abi-gen.jar", parent = 1) should_use_jvm_abi_gen = True else: class_abi_jar = None class_abi_output_dir = None jvm_abi_gen = None should_use_jvm_abi_gen = False should_kotlinc_run_incrementally = kotlin_toolchain.enable_incremental_compilation and incremental incremental_state_dir = declare_prefixed_output(actions, actions_identifier, "incremental_state", dir = True) compiling_deps_tset = get_compiling_deps_tset(actions, deps, additional_classpath_entries) # external javac does not support used classes track_class_usage = enable_used_classes and javac_tool == None and kotlin_toolchain.track_class_usage_plugin != None define_kotlincd_action = partial( _define_kotlincd_action, actions, java_toolchain, kotlin_toolchain, srcs, should_create_class_abi, class_abi_jar, jvm_abi_gen, class_abi_output_dir, optional_dirs, track_class_usage, compiling_deps_tset, debug_port, ) library_classpath_jars_tag = actions.artifact_tag() command_builder = _command_builder( javac_tool = javac_tool, label = label, srcs = srcs, remove_classes = remove_classes, annotation_processor_properties = annotation_processor_properties, plugin_params = plugin_params, manifest_file = manifest_file, source_level = source_level, target_level = target_level, compiling_deps_tset = compiling_deps_tset, bootclasspath_entries = bootclasspath_entries, system_image = custom_jdk_info.system_image if custom_jdk_info else None, abi_generation_mode = actual_abi_generation_mode, resources_map = resources_map, extra_arguments = extra_arguments, ) kotlin_extra_params = _encode_kotlin_extra_params( kotlin_toolchain = kotlin_toolchain, kotlin_compiler_plugins = kotlin_compiler_plugins, extra_kotlinc_arguments = extra_kotlinc_arguments, bootclasspath_entries = bootclasspath_entries, friend_paths = friend_paths, target_level = target_level, should_use_jvm_abi_gen = should_use_jvm_abi_gen, actual_abi_generation_mode = actual_abi_generation_mode, should_kotlinc_run_incrementally = should_kotlinc_run_incrementally, incremental_state_dir = incremental_state_dir, should_incremental_kotlinc_run_qe = incremental_qe_applied, language_version = language_version, ) library_command_builder = command_builder( kotlin_extra_params = kotlin_extra_params, provide_classpath_snapshot = should_kotlinc_run_incrementally, ) command = library_command_builder( build_mode = BuildMode("LIBRARY"), target_type = TargetType("library"), output_paths = output_paths, classpath_jars_tag = library_classpath_jars_tag, source_only_abi_compiling_deps = [], track_class_usage = track_class_usage, ) proto, used_jars_json = define_kotlincd_action( category_prefix = "", actions_identifier = actions_identifier, encoded_command = command, qualified_name = base_qualified_name(label), output_paths = output_paths, classpath_jars_tag = library_classpath_jars_tag, abi_dir = class_abi_output_dir if should_create_class_abi else None, target_type = TargetType("library"), is_creating_subtarget = is_creating_subtarget, incremental_state_dir = incremental_state_dir, should_action_run_incrementally = should_kotlinc_run_incrementally, ) final_jar_output = prepare_final_jar( actions = actions, actions_identifier = actions_identifier, output = None, output_paths = output_paths, additional_compiled_srcs = None, jar_builder = java_toolchain.jar_builder, jar_postprocessor = jar_postprocessor, jar_postprocessor_runner = java_toolchain.postprocessor_runner[RunInfo] if java_toolchain.postprocessor_runner else None, zip_scrubber = java_toolchain.zip_scrubber, ) if not is_creating_subtarget: kotlin_extra_params = _encode_kotlin_extra_params( kotlin_toolchain = kotlin_toolchain, kotlin_compiler_plugins = kotlin_compiler_plugins, extra_kotlinc_arguments = extra_kotlinc_arguments, bootclasspath_entries = bootclasspath_entries, friend_paths = friend_paths, target_level = target_level, should_use_jvm_abi_gen = should_use_jvm_abi_gen, actual_abi_generation_mode = actual_abi_generation_mode, should_kotlinc_run_incrementally = False, incremental_state_dir = None, should_incremental_kotlinc_run_qe = False, language_version = language_version, ) abi_command_builder = command_builder( kotlin_extra_params = kotlin_extra_params, provide_classpath_snapshot = False, ) # kotlincd does not support source abi class_abi, _, source_only_abi, classpath_abi, classpath_abi_dir = generate_abi_jars( actions = actions, actions_identifier = actions_identifier, label = label, abi_generation_mode = actual_abi_generation_mode, additional_compiled_srcs = None, is_building_android_binary = is_building_android_binary, class_abi_generator = java_toolchain.class_abi_generator, final_jar = final_jar_output.final_jar, compiling_deps_tset = compiling_deps_tset, source_only_abi_deps = source_only_abi_deps, class_abi_jar = class_abi_jar, class_abi_output_dir = class_abi_output_dir, track_class_usage = True, encode_abi_command = abi_command_builder, define_action = define_kotlincd_action, ) abi_jar_snapshot = generate_java_classpath_snapshot(actions, java_toolchain.cp_snapshot_generator, ClasspathSnapshotGranularity("CLASS_MEMBER_LEVEL"), classpath_abi, actions_identifier) return make_compile_outputs( full_library = final_jar_output.final_jar, preprocessed_library = final_jar_output.preprocessed_jar, class_abi = class_abi, source_only_abi = source_only_abi, classpath_abi = classpath_abi, classpath_abi_dir = classpath_abi_dir, required_for_source_only_abi = required_for_source_only_abi, annotation_processor_output = output_paths.annotations, incremental_state_dir = incremental_state_dir, abi_jar_snapshot = abi_jar_snapshot, used_jars_json = used_jars_json, ), proto else: full_jar_snapshot = generate_java_classpath_snapshot(actions, java_toolchain.cp_snapshot_generator, ClasspathSnapshotGranularity("CLASS_MEMBER_LEVEL"), final_jar_output.final_jar, actions_identifier) return make_compile_outputs( full_library = final_jar_output.final_jar, preprocessed_library = final_jar_output.preprocessed_jar, required_for_source_only_abi = required_for_source_only_abi, annotation_processor_output = output_paths.annotations, abi_jar_snapshot = full_jar_snapshot, used_jars_json = used_jars_json, ), proto def _encode_kotlin_extra_params( kotlin_toolchain: KotlinToolchainInfo, kotlin_compiler_plugins: dict, extra_kotlinc_arguments: list, bootclasspath_entries: list[Artifact], friend_paths: list[Dependency], target_level: int, should_use_jvm_abi_gen: bool, actual_abi_generation_mode: AbiGenerationMode, should_kotlinc_run_incrementally: bool, incremental_state_dir: Artifact | None, should_incremental_kotlinc_run_qe: bool, language_version: str): kosabiPluginOptionsMap = {} if kotlin_toolchain.kosabi_stubs_gen_plugin != None: kosabiPluginOptionsMap["kosabi_stubs_gen_plugin"] = kotlin_toolchain.kosabi_stubs_gen_plugin if kotlin_toolchain.kosabi_source_modifier_plugin != None: kosabiPluginOptionsMap["kosabi_source_modifier_plugin"] = kotlin_toolchain.kosabi_source_modifier_plugin if kotlin_toolchain.kosabi_applicability_plugin != None: kosabiPluginOptionsMap["kosabi_applicability_plugin"] = kotlin_toolchain.kosabi_applicability_plugin if kotlin_toolchain.kosabi_jvm_abi_gen_plugin != None: kosabiPluginOptionsMap["kosabi_jvm_abi_gen_plugin"] = kotlin_toolchain.kosabi_jvm_abi_gen_plugin return struct( extraClassPaths = bootclasspath_entries, standardLibraryClassPath = kotlin_toolchain.kotlin_stdlib[JavaLibraryInfo].library_output.full_library, annotationProcessingClassPath = kotlin_toolchain.annotation_processing_jar[JavaLibraryInfo].library_output.full_library, jvmAbiGenPlugin = kotlin_toolchain.jvm_abi_gen_plugin, kotlinCompilerPlugins = {plugin: {"params": plugin_options} if plugin_options else {} for plugin, plugin_options in kotlin_compiler_plugins.items()}, kosabiPluginOptions = struct(**kosabiPluginOptionsMap), friendPaths = [friend_path.library_output.abi for friend_path in map_idx(JavaLibraryInfo, friend_paths) if friend_path.library_output], kotlinHomeLibraries = kotlin_toolchain.kotlin_home_libraries, jvmTarget = get_kotlinc_compatible_target(str(target_level)), kosabiJvmAbiGenEarlyTerminationMessagePrefix = "exception: java.lang.RuntimeException: Terminating compilation. We're done with ABI.", shouldUseJvmAbiGen = should_use_jvm_abi_gen, shouldVerifySourceOnlyAbiConstraints = actual_abi_generation_mode == AbiGenerationMode("source_only"), shouldGenerateAnnotationProcessingStats = True, extraKotlincArguments = extra_kotlinc_arguments, depTrackerPlugin = kotlin_toolchain.track_class_usage_plugin, shouldKotlincRunIncrementally = should_kotlinc_run_incrementally, incrementalStateDir = incremental_state_dir.as_output() if incremental_state_dir else None, shouldIncrementalKotlicRunQe = should_incremental_kotlinc_run_qe, shouldUseStandaloneKosabi = kotlin_toolchain.kosabi_standalone, languageVersion = language_version, ) def _command_builder( javac_tool: [str, RunInfo, Artifact, None], label: Label, srcs: list[Artifact], remove_classes: list[str], annotation_processor_properties: AnnotationProcessorProperties, plugin_params: [PluginParams, None], manifest_file: Artifact | None, source_level: int, target_level: int, compiling_deps_tset: [JavaCompilingDepsTSet, None], bootclasspath_entries: list[Artifact], system_image: Artifact | None, abi_generation_mode: AbiGenerationMode, resources_map: dict[str, Artifact], extra_arguments: cmd_args): return partial( _encode_kotlin_command, javac_tool = javac_tool, label = label, srcs = srcs, remove_classes = remove_classes, annotation_processor_properties = annotation_processor_properties, plugin_params = plugin_params, manifest_file = manifest_file, source_level = source_level, target_level = target_level, compiling_deps_tset = compiling_deps_tset, bootclasspath_entries = bootclasspath_entries, system_image = system_image, abi_generation_mode = abi_generation_mode, resources_map = resources_map, extra_arguments = extra_arguments, ) def _encode_kotlin_command( javac_tool: [str, RunInfo, Artifact, None], label: Label, srcs: list[Artifact], remove_classes: list[str], annotation_processor_properties: AnnotationProcessorProperties, plugin_params: [PluginParams, None], manifest_file: Artifact | None, source_level: int, target_level: int, compiling_deps_tset: [JavaCompilingDepsTSet, None], bootclasspath_entries: list[Artifact], system_image: Artifact | None, abi_generation_mode: AbiGenerationMode, resources_map: dict[str, Artifact], extra_arguments: cmd_args, kotlin_extra_params: [struct, None], provide_classpath_snapshot: bool): return partial( encode_command, javac_tool = javac_tool, label = label, srcs = srcs, remove_classes = remove_classes, annotation_processor_properties = annotation_processor_properties, plugin_params = plugin_params, manifest_file = manifest_file, source_level = source_level, target_level = target_level, compiling_deps_tset = compiling_deps_tset, bootclasspath_entries = bootclasspath_entries, system_image = system_image, abi_generation_mode = abi_generation_mode, resources_map = resources_map, extra_arguments = extra_arguments, kotlin_extra_params = kotlin_extra_params, provide_classpath_snapshot = provide_classpath_snapshot, ) # buildifier: disable=uninitialized # buildifier: disable=unused-variable def _define_kotlincd_action( # provided by factory actions: AnalysisActions, java_toolchain: JavaToolchainInfo, kotlin_toolchain: KotlinToolchainInfo, srcs: list[Artifact], should_create_class_abi: bool, class_abi_jar: [Artifact, None], jvm_abi_gen: [cmd_args, None], class_abi_output_dir: [Artifact, None], optional_dirs: list[OutputArtifact], track_class_usage: bool, compiling_deps_tset: [JavaCompilingDepsTSet, None], debug_port: [int, None], # end of factory provided category_prefix: str, actions_identifier: [str, None], encoded_command: struct, qualified_name: str, output_paths: OutputPaths, classpath_jars_tag: ArtifactTag, abi_dir: Artifact | None, target_type: TargetType, source_only_abi_compiling_deps: list[JavaClasspathEntry] = [], is_creating_subtarget: bool = False, incremental_state_dir: Artifact | None = None, should_action_run_incrementally: bool = False): _unused = source_only_abi_compiling_deps proto = declare_prefixed_output(actions, actions_identifier, "jar_command.proto.json") compiler = kotlin_toolchain.kotlinc[DefaultInfo].default_outputs[0] exe, local_only = prepare_cd_exe( qualified_name, java = java_toolchain.java[RunInfo], class_loader_bootstrapper = kotlin_toolchain.class_loader_bootstrapper, compiler = compiler, main_class = kotlin_toolchain.kotlincd_main_class, worker = kotlin_toolchain.kotlincd_worker[WorkerInfo] if kotlin_toolchain.kotlincd_worker else None, target_specified_debug_port = debug_port, toolchain_specified_debug_port = kotlin_toolchain.kotlincd_debug_port, toolchain_specified_debug_target = kotlin_toolchain.kotlincd_debug_target, extra_jvm_args = kotlin_toolchain.kotlincd_jvm_args, extra_jvm_args_target = kotlin_toolchain.kotlincd_jvm_args_target, ) args = cmd_args() post_build_params = {} if target_type == TargetType("library") and should_create_class_abi: post_build_params["shouldCreateClassAbi"] = True post_build_params["libraryJar"] = output_paths.jar.as_output() post_build_params["abiJar"] = class_abi_jar.as_output() post_build_params["jvmAbiGen"] = jvm_abi_gen post_build_params["abiOutputDir"] = class_abi_output_dir.as_output() if target_type == TargetType("source_abi") or target_type == TargetType("source_only_abi"): post_build_params["abiJar"] = output_paths.jar.as_output() post_build_params["abiOutputDir"] = abi_dir.as_output() if optional_dirs: post_build_params["optionalDirs"] = optional_dirs if incremental_state_dir: post_build_params["incrementalStateDir"] = incremental_state_dir.as_output() dep_files = {} used_jars_json_output = None if not is_creating_subtarget and srcs and (kotlin_toolchain.dep_files == DepFiles("per_jar") or kotlin_toolchain.dep_files == DepFiles("per_class")) and target_type == TargetType("library") and track_class_usage: used_classes_json_outputs = [ cmd_args(output_paths.jar.as_output(), format = "{}/used-classes.json", parent = 1), cmd_args(output_paths.jar.as_output(), format = "{}/kotlin-used-classes.json", parent = 1), ] used_jars_json_output = declare_prefixed_output(actions, actions_identifier, "jar/used-jars.json") args = setup_dep_files( actions, actions_identifier, args, post_build_params, classpath_jars_tag, used_classes_json_outputs, used_jars_json_output, compiling_deps_tset.project_as_args("abi_to_abi_dir") if kotlin_toolchain.dep_files == DepFiles("per_class") and compiling_deps_tset else None, ) dep_files["classpath_jars"] = classpath_jars_tag kotlin_build_command = struct( buildCommand = encoded_command, postBuildParams = post_build_params, ) proto_with_inputs = actions.write_json(proto, kotlin_build_command, with_inputs = True) args.add( "--action-id", qualified_name, "--command-file", proto_with_inputs, ) if should_action_run_incrementally: args.add( "--incremental-metadata-file", _create_incremental_proto(actions, actions_identifier, kotlin_build_command, kotlin_toolchain.kotlin_version), ) incremental_run_params = { "metadata_env_var": "ACTION_METADATA", "metadata_path": "action_metadata.json", "no_outputs_cleanup": True, } if should_action_run_incrementally else {} actions.run( args, env = { "BUCK_CLASSPATH": compiler, "JAVACD_ABSOLUTE_PATHS_ARE_RELATIVE_TO_CWD": "1", }, category = "{}kotlincd_jar".format(category_prefix), identifier = actions_identifier, dep_files = dep_files, allow_dep_file_cache_upload = True, allow_cache_upload = True, exe = exe, local_only = local_only, low_pass_filter = False, weight = 2, error_handler = kotlin_toolchain.kotlin_error_handler, **incremental_run_params ) return proto, used_jars_json_output def _create_incremental_proto(actions: AnalysisActions, actions_identifier: [str, None], kotlin_build_command: struct, kotlin_version: str): incremental_meta_data_output = declare_prefixed_output(actions, actions_identifier, "incremental_metadata.proto.json") incremental_meta_data = struct( version = 1, track_class_usage = kotlin_build_command.buildCommand.baseJarCommand.trackClassUsage, should_use_jvm_abi_gen = kotlin_build_command.buildCommand.kotlinExtraParams.shouldUseJvmAbiGen, kotlin_version = kotlin_version, ) return actions.write_json(incremental_meta_data_output, incremental_meta_data, with_inputs = True)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systeminit/si'

If you have feedback or need assistance with the MCP directory API, please join our Discord server