mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-05 19:28:46 +02:00
Re-applies commit1120b9084e(reverted inef2c1d47ccduring install debugging). The install failure was proven to be the oversized watch binary (fixed by DEAD_CODE_STRIPPING), not the bundle-id mechanism — which was verified to produce a byte-identical artifact for ph.telegra.Telegraph. xcodebuild bakes PRODUCT_BUNDLE_IDENTIFIER=<host>.watchkitapp and the watch Info.plist derives WKCompanionAppBundleIdentifier via $(PRODUCT_BUNDLE_IDENTIFIER:base), so the embedded watch app is correct for any host (ph.telegra.Telegraph and org.telegram.TelegramInternal/enterprise) with no post-build plist patching. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
144 lines
6.6 KiB
Python
144 lines
6.6 KiB
Python
"""Embeds the standalone, xcodebuild-built tgwatch watch app into the Bazel iOS build.
|
|
|
|
`apple_prebuilt_watchos_application` runs `xcodebuild` (via prebuilt_watchos_build.sh)
|
|
against an exported tgwatch source tree, optionally codesigns the result, and exposes
|
|
it through the providers that `ios_application(watch_application = ...)` consumes:
|
|
|
|
* AppleBundleInfo — bundle metadata (the host reads only `.product_type`).
|
|
* AppleEmbeddableInfo — `watch_bundles` (the zipped .app placed under Watch/).
|
|
|
|
The watch source tree is the committed in-repo snapshot at `Telegram/WatchApp/` (tracked
|
|
inputs). To update it, re-sync from the standalone tgwatch repo via
|
|
`tgwatch/tools/export-sources.sh`.
|
|
|
|
Notes on the rules_apple providers used here:
|
|
* AppleBundleInfo's public init is banned; we build it with the internal raw
|
|
initializer `new_applebundleinfo` (rules_apple is vendored + pinned in this repo,
|
|
so depending on the internal label is safe).
|
|
"""
|
|
|
|
load(
|
|
"@build_bazel_rules_apple//apple/internal:providers.bzl",
|
|
"new_applebundleinfo",
|
|
"new_watchosapplicationbundleinfo",
|
|
)
|
|
load("@build_bazel_rules_apple//apple/internal/providers:embeddable_info.bzl", "AppleEmbeddableInfo")
|
|
|
|
def _apple_prebuilt_watchos_application_impl(ctx):
|
|
# The watch app is built from the committed in-repo snapshot at Telegram/WatchApp,
|
|
# tracked as inputs (incremental + cacheable).
|
|
source_path = ctx.attr.in_repo_source_dir
|
|
api_id = ctx.var.get("watchApiId", "0")
|
|
api_hash = ctx.var.get("watchApiHash", "placeholder")
|
|
identity = ctx.var.get("watchSigningIdentity", "")
|
|
|
|
# The provisioning profile is an external, machine-specific absolute path passed via
|
|
# --define rather than a Bazel label, so the gitignored profile need not be exposed as
|
|
# a target. The local action reads it directly. Empty => unsigned build; when set but
|
|
# the identity is empty, the worker derives the signing identity from the profile.
|
|
profile = ctx.var.get("watchProvisioningProfile", "")
|
|
# The embedded watch app's CFBundleShortVersionString / CFBundleVersion must match
|
|
# the host app, or rules_apple's child-version verification fails. Source the
|
|
# marketing version from versions.json (same as the host's VersionInfoPlist) and the
|
|
# build version from buildNumber (Make.py always emits --define=buildNumber).
|
|
build_number = ctx.var.get("buildNumber", "1")
|
|
archive = ctx.actions.declare_file(ctx.label.name + ".zip")
|
|
# The host ios_application reads the watch app's Info.plist (via AppleBundleInfo.infoplist)
|
|
# to verify WKCompanionAppBundleIdentifier against the host bundle id, so expose it as a
|
|
# separate output (resources.bzl bundle_verification crashes on a None infoplist).
|
|
infoplist = ctx.actions.declare_file(ctx.label.name + "_Info.plist")
|
|
|
|
# Track the in-repo snapshot so the watch build re-runs only when it changes.
|
|
inputs = [ctx.file._worker, ctx.file.versions_json] + ctx.files.srcs
|
|
exec_requirements = {
|
|
"no-sandbox": "1",
|
|
"no-remote": "1",
|
|
"local": "1",
|
|
"requires-network": "1",
|
|
}
|
|
|
|
ctx.actions.run(
|
|
executable = "/bin/bash",
|
|
arguments = [
|
|
ctx.file._worker.path,
|
|
source_path,
|
|
archive.path,
|
|
api_id,
|
|
api_hash,
|
|
identity,
|
|
profile,
|
|
infoplist.path,
|
|
ctx.file.versions_json.path,
|
|
build_number,
|
|
# Watch app bundle id ("<host>.watchkitapp"). xcodebuild bakes it as
|
|
# PRODUCT_BUNDLE_IDENTIFIER so the signed CFBundleIdentifier matches the host
|
|
# config; the Info.plist derives WKCompanionAppBundleIdentifier from it via
|
|
# $(PRODUCT_BUNDLE_IDENTIFIER:base). Keeps the build dynamic across hosts with
|
|
# no post-build plist mutation (xcodebuild bakes, the worker signs once).
|
|
ctx.attr.bundle_id,
|
|
],
|
|
inputs = inputs,
|
|
outputs = [archive, infoplist],
|
|
mnemonic = "PrebuiltWatchosBuild",
|
|
progress_message = "Building%s watch app via xcodebuild" % (" + signing" if profile else ""),
|
|
execution_requirements = exec_requirements,
|
|
use_default_shell_env = True,
|
|
)
|
|
|
|
return [
|
|
DefaultInfo(files = depset([archive])),
|
|
new_applebundleinfo(
|
|
archive = archive,
|
|
bundle_id = ctx.attr.bundle_id,
|
|
bundle_name = ctx.attr.bundle_name,
|
|
bundle_extension = ".app",
|
|
platform_type = "watchos",
|
|
# Must be a single-target watchOS app (NOT watch2_application) so the host
|
|
# skips the watchos_stub partial (see ios_rules.bzl product_type check).
|
|
product_type = "com.apple.product-type.application",
|
|
minimum_os_version = ctx.attr.minimum_os_version,
|
|
minimum_deployment_os_version = ctx.attr.minimum_os_version,
|
|
infoplist = infoplist,
|
|
binary = None,
|
|
entitlements = None,
|
|
# Best-effort constant; the host ios_application reads only product_type.
|
|
uses_swift = True,
|
|
extension_safe = False,
|
|
),
|
|
# Marker provider required by ios_application's watch_application attr
|
|
# (providers = [[AppleBundleInfo, WatchosApplicationBundleInfo]]).
|
|
new_watchosapplicationbundleinfo(),
|
|
AppleEmbeddableInfo(
|
|
# The signed (or unsigned) .app archive, expanded into the host's Watch/ section.
|
|
watch_bundles = depset([archive]),
|
|
# Empty: the worker signs everything inside the watch app itself.
|
|
signed_frameworks = depset(),
|
|
),
|
|
]
|
|
|
|
apple_prebuilt_watchos_application = rule(
|
|
implementation = _apple_prebuilt_watchos_application_impl,
|
|
attrs = {
|
|
"bundle_id": attr.string(default = "ph.telegra.Telegraph.watchkitapp"),
|
|
"bundle_name": attr.string(default = "tgwatch Watch App"),
|
|
"minimum_os_version": attr.string(default = "26.0"),
|
|
"srcs": attr.label(
|
|
default = "//Telegram/WatchApp:sources",
|
|
allow_files = True,
|
|
doc = "Committed in-repo watch source snapshot (tracked inputs).",
|
|
),
|
|
"in_repo_source_dir": attr.string(
|
|
default = "Telegram/WatchApp",
|
|
doc = "Execroot-relative path to the committed snapshot (must match the package of 'srcs').",
|
|
),
|
|
"versions_json": attr.label(
|
|
allow_single_file = True,
|
|
default = "//:versions.json",
|
|
doc = "Source of the marketing version (key 'app'), kept in sync with the host app.",
|
|
),
|
|
"_worker": attr.label(
|
|
default = "//Telegram:prebuilt_watchos_build.sh",
|
|
allow_single_file = True,
|
|
),
|
|
},
|
|
)
|