load("@prelude//http_archive/exec_deps.bzl", "HttpArchiveExecDeps") load(":releases.bzl", "releases") ProtocReleaseInfo = provider(fields = [ "version", "url", "sha256", ]) def _get_protoc_release( version: str, platform: str) -> ProtocReleaseInfo: if not version in releases: fail("Unknown protoc release version '{}'. Available versions: {}".format( version, ", ".join(releases.keys()), )) protoc_version = releases[version] artifact = "protoc-{}-{}.zip".format(version, platform) if not artifact in protoc_version: fail("Unsupported platform '{}'. Available artifacts: {}".format( platform, ", ".join(protoc_version.keys()), )) protoc_artifact = protoc_version[artifact] return ProtocReleaseInfo( version = version, url = protoc_artifact["url"], sha256 = protoc_artifact["sha256"], ) def _turn_http_archive_into_protoc_distribution( providers: ProviderCollection, protoc_filename: str) -> list[Provider]: downloads = providers[DefaultInfo].sub_targets include = downloads["include"][DefaultInfo] protoc = downloads[protoc_filename][DefaultInfo] return [DefaultInfo( sub_targets = { "google_protobuf": [include], "protoc": [ protoc, RunInfo(args = protoc.default_outputs[0]), ], }, )] def _download_protoc_distribution_impl(ctx: AnalysisContext) -> Promise: protoc_filename = "bin/protoc" + ctx.attrs.exe_extension # @lint-ignore BUCKLINT: avoid "Direct usage of native rules is not allowed." return ctx.actions.anon_target(native.http_archive, { "exec_deps": ctx.attrs._http_archive_exec_deps, "sha256": ctx.attrs.sha256, "sub_targets": [ protoc_filename, "include", ], "urls": [ctx.attrs.url], }).promise.map(lambda providers: _turn_http_archive_into_protoc_distribution( providers = providers, protoc_filename = protoc_filename, )) download_protoc_distribution = rule( impl = _download_protoc_distribution_impl, attrs = { "exe_extension": attrs.string(), "sha256": attrs.string(), "url": attrs.string(), "_http_archive_exec_deps": attrs.default_only(attrs.exec_dep(providers = [HttpArchiveExecDeps], default = "prelude//http_archive/tools:exec_deps")), }, ) def _host_platform(): os = host_info().os arch = host_info().arch if os.is_linux and arch.is_x86_64: return "linux-x86_64" elif os.is_linux and arch.is_aarch64: return "linux-aarch_64" elif os.is_macos and arch.is_x86_64: return "osx-x86_64" elif os.is_macos and arch.is_aarch64: return "osx-aarch_64" elif os.is_windows and arch.is_x86_64: return "win64" else: fail("Unknown platform: os={}, arch={}".format(os, arch)) def protoc_distribution( name: str, version: str, platform: [None, str] = None): if platform == None: platform = _host_platform() exe_extension = ".exe" if platform.startswith("win") else "" release = _get_protoc_release(version, platform) download_protoc_distribution( name = name, url = release.url, sha256 = release.sha256, exe_extension = exe_extension, )