Skip to main content
Glama
swift_incremental_support.bzl6.42 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//apple/swift:swift_toolchain_types.bzl", "SwiftObjectFormat") load("@prelude//apple/swift:swift_types.bzl", "SwiftCompilationModes") load( "@prelude//cxx:cxx_sources.bzl", "CxxSrcWithFlags", # @unused Used as a type ) load("@prelude//utils:buckconfig.bzl", "read_bool") load(":swift_toolchain.bzl", "get_swift_toolchain_info") _SKIP_INCREMENTAL_OUTPUTS = read_bool("apple", "skip_swift_incremental_outputs", False, False, True) _WriteOutputFileMapOutput = record( artifacts = field(list[Artifact]), outputs = field(list[Artifact]), output_map_artifact = field(Artifact), swiftdeps = field(list[Artifact]), ) IncrementalCompilationOutput = record( incremental_flags_cmd = field(cmd_args), artifacts = field(list[Artifact]), output_map_artifact = field(Artifact), num_threads = field(int), swiftdeps = field(list[Artifact]), ) SwiftCompilationMode = enum(*SwiftCompilationModes) # The maxmium number of threads, we don't use # host_info to prevent cache misses across # different hardware models. _MAX_NUM_THREADS = 6 # This is the default, but specifying it explicitly # is clearer. _SWIFT_BATCH_SIZE = 25 def should_build_swift_incrementally(ctx: AnalysisContext) -> bool: toolchain = get_swift_toolchain_info(ctx) # Incremental builds are only supported when object files are generated. if toolchain.object_format != SwiftObjectFormat("object"): return False return SwiftCompilationMode(ctx.attrs.swift_compilation_mode) == SwiftCompilationMode("incremental") def get_incremental_object_compilation_flags( ctx: AnalysisContext, srcs: list[CxxSrcWithFlags], output_swiftmodule: Artifact, output_header: Artifact) -> IncrementalCompilationOutput: output_file_map = _write_output_file_map(ctx, srcs) return _get_incremental_compilation_flags_and_objects( output_file_map, output_swiftmodule, output_header, len(srcs), ) def _get_incremental_num_threads(num_srcs: int) -> int: if num_srcs == 0: return 1 src_threads = (num_srcs + _SWIFT_BATCH_SIZE - 1) // _SWIFT_BATCH_SIZE return min(_MAX_NUM_THREADS, src_threads) def _get_incremental_compilation_flags_and_objects( output_file_map: _WriteOutputFileMapOutput, output_swiftmodule: Artifact, output_header: Artifact, num_srcs: int) -> IncrementalCompilationOutput: cmd = cmd_args( [ "-disable-cmo", "-emit-object", "-enable-batch-mode", "-enable-incremental-imports", "-experimental-emit-module-separately", "-incremental", "-j", str(_MAX_NUM_THREADS), "-driver-batch-size-limit", str(_SWIFT_BATCH_SIZE), "-output-file-map", # When skipping incremental outputs, we write the contents of the output_file_map in the swift wrapper # and need to ensure this is an output file (vs being an input in normal cases) output_file_map.output_map_artifact.as_output() if _SKIP_INCREMENTAL_OUTPUTS else output_file_map.output_map_artifact, "-emit-objc-header", "-emit-objc-header-path", output_header.as_output(), "-emit-module", "-emit-module-path", output_swiftmodule.as_output(), ], hidden = [output.as_output() for output in output_file_map.outputs], ) if _SKIP_INCREMENTAL_OUTPUTS: cmd.add("-skip-incremental-outputs") return IncrementalCompilationOutput( incremental_flags_cmd = cmd, artifacts = output_file_map.artifacts, output_map_artifact = output_file_map.output_map_artifact, num_threads = _get_incremental_num_threads(num_srcs), swiftdeps = output_file_map.swiftdeps, ) def _write_output_file_map( ctx: AnalysisContext, srcs: list[CxxSrcWithFlags]) -> _WriteOutputFileMapOutput: if _SKIP_INCREMENTAL_OUTPUTS: all_outputs = [] swiftdeps = [] artifacts = [] for src in srcs: file_name = src.file.basename output_artifact = ctx.actions.declare_output("__swift_incremental__/objects/" + file_name + ".o") artifacts.append(output_artifact) all_outputs.append(output_artifact) # When skipping incremental outputs, we write the contents of the output_file_map in the swift wrapper # and need to ensure this is an output file (vs being an input in normal cases) output_map_artifact = ctx.actions.declare_output("__swift_incremental__/output_file_map.json") else: # swift-driver doesn't respect extension for root swiftdeps file and it always has to be `.priors`. module_swiftdeps = ctx.actions.declare_output("__swift_incremental__/swiftdeps/module-build-record.priors") output_file_map = { "": { "swift-dependencies": module_swiftdeps, }, } all_outputs = [module_swiftdeps] swiftdeps = [module_swiftdeps] artifacts = [] for src in srcs: file_name = src.file.basename output_artifact = ctx.actions.declare_output("__swift_incremental__/objects/" + file_name + ".o") artifacts.append(output_artifact) all_outputs.append(output_artifact) swiftdeps_artifact = ctx.actions.declare_output("__swift_incremental__/swiftdeps/" + file_name + ".swiftdeps") output_file_map[src.file] = { "object": output_artifact, "swift-dependencies": swiftdeps_artifact, } swiftdeps.append(swiftdeps_artifact) all_outputs.append(swiftdeps_artifact) output_map_artifact = ctx.actions.write_json("__swift_incremental__/output_file_map.json", output_file_map, pretty = True) return _WriteOutputFileMapOutput( artifacts = artifacts, outputs = all_outputs, output_map_artifact = output_map_artifact, swiftdeps = swiftdeps, )

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