Merge branch 'refactoring/build-system'

This commit is contained in:
Ali 2021-01-13 13:20:51 +04:00
commit 34bd191e68
22 changed files with 891 additions and 235 deletions

View File

@ -1,3 +1,7 @@
load("@bazel_skylib//rules:common_settings.bzl",
"bool_flag",
)
load("@build_bazel_rules_apple//apple:ios.bzl",
"ios_application",
"ios_extension",
@ -18,13 +22,10 @@ load("//build-system/bazel-utils:plist_fragment.bzl",
)
load(
"//build-input/data:variables.bzl",
"telegram_build_number",
"telegram_version",
"@build_configuration//:variables.bzl",
"telegram_bundle_id",
"telegram_aps_environment",
"telegram_team_id",
"telegram_disable_extensions",
)
config_setting(
@ -34,6 +35,25 @@ config_setting(
},
)
bool_flag(
name = "disableExtensions",
build_setting_default = False,
visibility = ["//visibility:public"],
)
string_flag(
name = "buildNumber",
build_setting_default = "10000",
visibility = ["//visibility:public"],
)
config_setting(
name = "disableExtensionsSetting",
flag_values = {
":disableExtensions": "True",
},
)
genrule(
name = "empty",
outs = ["empty.swift"],
@ -190,14 +210,20 @@ swift_library(
)
plist_fragment(
name = "AdditionalInfoPlist",
name = "BuildNumberInfoPlist",
extension = "plist",
template =
"""
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundleVersion</key>
<string>{telegram_build_number}</string>
<string>{buildNumber}</string>
"""
)
plist_fragment(
name = "UrlTypesInfoPlist",
extension = "plist",
template =
"""
<key>CFBundleURLTypes</key>
<array>
<dict>
@ -210,16 +236,6 @@ plist_fragment(
<string>telegram</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleURLName</key>
<string>{telegram_bundle_id}.ton</string>
<key>CFBundleURLSchemes</key>
<array>
<string>ton</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
@ -232,8 +248,6 @@ plist_fragment(
</dict>
</array>
""".format(
telegram_version = telegram_version,
telegram_build_number = telegram_build_number,
telegram_bundle_id = telegram_bundle_id,
)
)
@ -371,13 +385,8 @@ plist_fragment(
template =
"""
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundleVersion</key>
<string>{telegram_build_number}</string>
""".format(
telegram_version = telegram_version,
telegram_build_number = telegram_build_number,
)
<string>{telegramVersion}</string>
"""
)
plist_fragment(
@ -478,11 +487,12 @@ watchos_extension(
infoplists = [
":WatchExtensionInfoPlist",
":VersionInfoPlist",
":BuildNumberInfoPlist",
":AppNameInfoPlist",
":WatchExtensionNSExtensionInfoPlist",
],
minimum_os_version = "5.0",
provisioning_profile = "//build-input/data/provisioning-profiles:WatchExtension.mobileprovision",
provisioning_profile = "@build_configuration//provisioning:WatchExtension.mobileprovision",
resources = [
":TelegramWatchExtensionResources",
],
@ -505,11 +515,12 @@ watchos_application(
infoplists = [
":WatchAppInfoPlist",
":VersionInfoPlist",
"BuildNumberInfoPlist",
":AppNameInfoPlist",
":WatchAppCompanionInfoPlist",
],
minimum_os_version = "5.0",
provisioning_profile = "//build-input/data/provisioning-profiles:WatchApp.mobileprovision",
provisioning_profile = "@build_configuration//provisioning:WatchApp.mobileprovision",
resources = [
":TelegramWatchAppResources",
":TelegramWatchAppAssets",
@ -528,20 +539,14 @@ plist_fragment(
"""
<key>CFBundleIdentifier</key>
<string>{telegram_bundle_id}.MtProtoKit</string>
<key>CFBundleVersion</key>
<string>{telegram_build_number}</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleName</key>
<string>MtProtoKit</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
telegram_build_number = telegram_build_number,
)
)
@ -556,6 +561,8 @@ ios_framework(
],
infoplists = [
":MtProtoKitInfoPlist",
":BuildNumberInfoPlist",
":VersionInfoPlist",
],
minimum_os_version = "9.0",
ipa_post_processor = strip_framework,
@ -571,20 +578,14 @@ plist_fragment(
"""
<key>CFBundleIdentifier</key>
<string>{telegram_bundle_id}.SwiftSignalKit</string>
<key>CFBundleVersion</key>
<string>{telegram_build_number}</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleName</key>
<string>SwiftSignalKit</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
telegram_build_number = telegram_build_number,
)
)
@ -599,6 +600,8 @@ ios_framework(
],
infoplists = [
":SwiftSignalKitInfoPlist",
":BuildNumberInfoPlist",
":VersionInfoPlist",
],
minimum_os_version = "9.0",
ipa_post_processor = strip_framework,
@ -614,20 +617,14 @@ plist_fragment(
"""
<key>CFBundleIdentifier</key>
<string>{telegram_bundle_id}.Postbox</string>
<key>CFBundleVersion</key>
<string>{telegram_build_number}</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleName</key>
<string>Postbox</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
telegram_build_number = telegram_build_number,
)
)
@ -642,6 +639,8 @@ ios_framework(
],
infoplists = [
":PostboxInfoPlist",
":BuildNumberInfoPlist",
":VersionInfoPlist",
],
frameworks = [
":SwiftSignalKitFramework",
@ -660,20 +659,14 @@ plist_fragment(
"""
<key>CFBundleIdentifier</key>
<string>{telegram_bundle_id}.TelegramApi</string>
<key>CFBundleVersion</key>
<string>{telegram_build_number}</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleName</key>
<string>TelegramApi</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
telegram_build_number = telegram_build_number,
)
)
@ -688,6 +681,8 @@ ios_framework(
],
infoplists = [
":TelegramApiInfoPlist",
":BuildNumberInfoPlist",
":VersionInfoPlist",
],
minimum_os_version = "9.0",
ipa_post_processor = strip_framework,
@ -703,20 +698,14 @@ plist_fragment(
"""
<key>CFBundleIdentifier</key>
<string>{telegram_bundle_id}.SyncCore</string>
<key>CFBundleVersion</key>
<string>{telegram_build_number}</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleName</key>
<string>SyncCore</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
telegram_build_number = telegram_build_number,
)
)
@ -731,6 +720,8 @@ ios_framework(
],
infoplists = [
":SyncCoreInfoPlist",
":BuildNumberInfoPlist",
":VersionInfoPlist",
],
frameworks = [
":SwiftSignalKitFramework",
@ -750,20 +741,14 @@ plist_fragment(
"""
<key>CFBundleIdentifier</key>
<string>{telegram_bundle_id}.TelegramCore</string>
<key>CFBundleVersion</key>
<string>{telegram_build_number}</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleName</key>
<string>TelegramCore</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
telegram_build_number = telegram_build_number,
)
)
@ -778,13 +763,14 @@ ios_framework(
],
infoplists = [
":TelegramCoreInfoPlist",
":BuildNumberInfoPlist",
":VersionInfoPlist",
],
frameworks = [
":MtProtoKitFramework",
":SwiftSignalKitFramework",
":PostboxFramework",
":SyncCoreFramework",
#":TelegramApiFramework",
],
minimum_os_version = "9.0",
ipa_post_processor = strip_framework,
@ -800,20 +786,14 @@ plist_fragment(
"""
<key>CFBundleIdentifier</key>
<string>{telegram_bundle_id}.AsyncDisplayKit</string>
<key>CFBundleVersion</key>
<string>{telegram_build_number}</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleName</key>
<string>AsyncDisplayKit</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
telegram_build_number = telegram_build_number,
)
)
@ -828,6 +808,8 @@ ios_framework(
],
infoplists = [
":AsyncDisplayKitInfoPlist",
":BuildNumberInfoPlist",
":VersionInfoPlist",
],
minimum_os_version = "9.0",
ipa_post_processor = strip_framework,
@ -843,20 +825,14 @@ plist_fragment(
"""
<key>CFBundleIdentifier</key>
<string>{telegram_bundle_id}.Display</string>
<key>CFBundleVersion</key>
<string>{telegram_build_number}</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleName</key>
<string>Display</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
telegram_build_number = telegram_build_number,
)
)
@ -914,6 +890,8 @@ ios_framework(
],
infoplists = [
":DisplayInfoPlist",
":BuildNumberInfoPlist",
":VersionInfoPlist",
],
frameworks = [
":SwiftSignalKitFramework",
@ -933,20 +911,14 @@ plist_fragment(
"""
<key>CFBundleIdentifier</key>
<string>{telegram_bundle_id}.TelegramUI</string>
<key>CFBundleVersion</key>
<string>{telegram_build_number}</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleName</key>
<string>TelegramUI</string>
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
""".format(
telegram_bundle_id = telegram_bundle_id,
telegram_version = telegram_version,
telegram_build_number = telegram_build_number,
)
)
@ -961,12 +933,13 @@ ios_framework(
],
infoplists = [
":TelegramUIInfoPlist",
":BuildNumberInfoPlist",
":VersionInfoPlist",
],
frameworks = [
":MtProtoKitFramework",
":SwiftSignalKitFramework",
":PostboxFramework",
#":TelegramApiFramework",
":SyncCoreFramework",
":TelegramCoreFramework",
":AsyncDisplayKitFramework",
@ -1052,10 +1025,11 @@ ios_extension(
infoplists = [
":ShareInfoPlist",
":VersionInfoPlist",
":BuildNumberInfoPlist",
":AppNameInfoPlist",
],
minimum_os_version = "9.0",
provisioning_profile = "//build-input/data/provisioning-profiles:Share.mobileprovision",
provisioning_profile = "@build_configuration//provisioning:Share.mobileprovision",
deps = [":ShareExtensionLib"],
frameworks = [
":TelegramUIFramework"
@ -1120,10 +1094,11 @@ ios_extension(
infoplists = [
":NotificationContentInfoPlist",
":VersionInfoPlist",
":BuildNumberInfoPlist",
":AppNameInfoPlist",
],
minimum_os_version = "10.0",
provisioning_profile = "//build-input/data/provisioning-profiles:NotificationContent.mobileprovision",
provisioning_profile = "@build_configuration//provisioning:NotificationContent.mobileprovision",
deps = [":NotificationContentExtensionLib"],
frameworks = [
":TelegramUIFramework"
@ -1191,11 +1166,12 @@ ios_extension(
infoplists = [
":WidgetInfoPlist",
":VersionInfoPlist",
":BuildNumberInfoPlist",
":AppNameInfoPlist",
],
minimum_os_version = "14.0",
provides_main = True,
provisioning_profile = "//build-input/data/provisioning-profiles:Widget.mobileprovision",
provisioning_profile = "@build_configuration//provisioning:Widget.mobileprovision",
deps = [":WidgetExtensionLib"],
frameworks = [
":SwiftSignalKitFramework",
@ -1280,16 +1256,16 @@ ios_extension(
infoplists = [
":IntentsInfoPlist",
":VersionInfoPlist",
":BuildNumberInfoPlist",
":AppNameInfoPlist",
],
minimum_os_version = "10.0",
provisioning_profile = "//build-input/data/provisioning-profiles:Intents.mobileprovision",
provisioning_profile = "@build_configuration//provisioning:Intents.mobileprovision",
deps = [":IntentsExtensionLib"],
frameworks = [
":SwiftSignalKitFramework",
":PostboxFramework",
":TelegramCoreFramework",
#":TelegramApiFramework",
":SyncCoreFramework",
],
)
@ -1331,17 +1307,16 @@ ios_extension(
infoplists = [
":NotificationServiceInfoPlist",
":VersionInfoPlist",
":BuildNumberInfoPlist",
":AppNameInfoPlist",
],
minimum_os_version = "10.0",
provisioning_profile = "//build-input/data/provisioning-profiles:NotificationService.mobileprovision",
provisioning_profile = "@build_configuration//provisioning:NotificationService.mobileprovision",
deps = ["//Telegram/NotificationService:NotificationServiceExtensionLib"],
frameworks = [
":MtProtoKitFramework",
":SwiftSignalKitFramework",
":PostboxFramework",
#":TelegramApiFramework",
#":SyncCoreFramework",
],
)
@ -1522,11 +1497,13 @@ ios_application(
),
families = ["iphone", "ipad"],
minimum_os_version = "9.0",
provisioning_profile = "//build-input/data/provisioning-profiles:Telegram.mobileprovision",
provisioning_profile = "@build_configuration//provisioning:Telegram.mobileprovision",
entitlements = ":TelegramEntitlements.entitlements",
infoplists = [
":TelegramInfoPlist",
":AdditionalInfoPlist",
":BuildNumberInfoPlist",
":VersionInfoPlist",
":UrlTypesInfoPlist",
],
ipa_post_processor = ":AddAlternateIcons",
resources = [
@ -1547,14 +1524,16 @@ ios_application(
strings = [
":AppStringResources",
],
extensions = [
] if telegram_disable_extensions else [
extensions = select({
":disableExtensionsSetting": [],
"//conditions:default": [
":ShareExtension",
":NotificationContentExtension",
":NotificationServiceExtension",
":IntentsExtension",
":WidgetExtension",
],
}),
watch_application = ":TelegramWatchApp",
deps = [
":Main",

View File

@ -0,0 +1,148 @@
import json
import os
import platform
import subprocess
def is_apple_silicon():
if platform.processor() == 'arm':
return True
else:
return False
def get_clean_env():
clean_env = os.environ.copy()
clean_env['PATH'] = '/usr/bin:/bin:/usr/sbin:/sbin'
return clean_env
def resolve_executable(program):
def is_executable(fpath):
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
for path in get_clean_env()["PATH"].split(os.pathsep):
executable_file = os.path.join(path, program)
if is_executable(executable_file):
return executable_file
return None
def run_executable_with_output(path, arguments):
executable_path = resolve_executable(path)
if executable_path is None:
raise Exception('Could not resolve {} to a valid executable file'.format(path))
process = subprocess.Popen(
[executable_path] + arguments,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
env=get_clean_env()
)
output_data, _ = process.communicate()
output_string = output_data.decode('utf-8')
return output_string
def call_executable(arguments, use_clean_environment=True, check_result=True):
executable_path = resolve_executable(arguments[0])
if executable_path is None:
raise Exception('Could not resolve {} to a valid executable file'.format(arguments[0]))
if use_clean_environment:
resolved_env = get_clean_env()
else:
resolved_env = os.environ
resolved_arguments = [executable_path] + arguments[1:]
if check_result:
subprocess.check_call(resolved_arguments, env=resolved_env)
else:
subprocess.call(resolved_arguments, env=resolved_env)
def get_bazel_version(bazel_path):
command_result = run_executable_with_output(bazel_path, ['--version']).strip('\n')
if not command_result.startswith('bazel '):
raise Exception('{} is not a valid bazel binary'.format(bazel_path))
command_result.replace('bazel ', '')
return command_result
def get_xcode_version():
xcode_path = run_executable_with_output('xcode-select', ['-p']).strip('\n')
if not os.path.isdir(xcode_path):
print('The path reported by \'xcode-select -p\' does not exist')
exit(1)
plist_path = '{}/../Info.plist'.format(xcode_path)
info_plist_lines = run_executable_with_output('plutil', [
'-p', plist_path
]).split('\n')
pattern = 'CFBundleShortVersionString" => '
for line in info_plist_lines:
index = line.find(pattern)
if index != -1:
version = line[index + len(pattern):].strip('"')
return version
print('Could not parse the Xcode version from {}'.format(plist_path))
exit(1)
class BuildEnvironment:
def __init__(
self,
base_path,
bazel_path,
bazel_x86_64_path,
override_bazel_version,
override_xcode_version
):
self.base_path = os.path.expanduser(base_path)
self.bazel_path = os.path.expanduser(bazel_path)
if bazel_x86_64_path is not None:
self.bazel_x86_64_path = os.path.expanduser(bazel_x86_64_path)
else:
self.bazel_x86_64_path = None
configuration_path = os.path.join(self.base_path, 'versions.json')
with open(configuration_path) as file:
configuration_dict = json.load(file)
if configuration_dict['app'] is None:
raise Exception('Missing app version in {}'.format(configuration_path))
else:
self.app_version = configuration_dict['app']
if configuration_dict['bazel'] is None:
raise Exception('Missing bazel version in {}'.format(configuration_path))
else:
self.bazel_version = configuration_dict['bazel']
if configuration_dict['xcode'] is None:
raise Exception('Missing xcode version in {}'.format(configuration_path))
else:
self.xcode_version = configuration_dict['xcode']
actual_bazel_version = get_bazel_version(self.bazel_path)
if actual_bazel_version != self.bazel_version:
if override_bazel_version:
print('Overriding the required bazel version {} with {} as reported by {}'.format(
self.bazel_version, actual_bazel_version, self.bazel_path))
self.bazel_version = actual_bazel_version
else:
print('Required bazel version is {}, but {} is reported by {}'.format(
self.bazel_version, actual_bazel_version, self.bazel_path))
exit(1)
actual_xcode_version = get_xcode_version()
if actual_xcode_version != self.xcode_version:
if override_xcode_version:
print('Overriding the required Xcode version {} with {} as reported by \'xcode-select -p\''.format(
self.xcode_version, actual_xcode_version, self.bazel_path))
self.xcode_version = actual_xcode_version
else:
print('Required Xcode version is {}, but {} is reported by \'xcode-select -p\''.format(
self.xcode_version, actual_xcode_version, self.bazel_path))
exit(1)

472
build-system/Make/Make.py Normal file
View File

@ -0,0 +1,472 @@
#!/bin/python3
import argparse
import os
import shlex
import sys
import tempfile
from BuildEnvironment import is_apple_silicon, resolve_executable, call_executable, BuildEnvironment
from ProjectGeneration import generate
class BazelCommandLine:
def __init__(self, bazel_path, bazel_x86_64_path, override_bazel_version, override_xcode_version):
self.build_environment = BuildEnvironment(
base_path=os.getcwd(),
bazel_path=bazel_path,
bazel_x86_64_path=bazel_x86_64_path,
override_bazel_version=override_bazel_version,
override_xcode_version=override_xcode_version
)
self.remote_cache = None
self.cache_dir = None
self.additional_args = None
self.build_number = None
self.configuration_args = None
self.configuration_path = None
self.common_args = [
# https://docs.bazel.build/versions/master/command-line-reference.html
# Ask bazel to print the actual resolved command line options.
'--announce_rc',
# https://github.com/bazelbuild/rules_swift
# If enabled, Swift compilation actions will use the same global Clang module
# cache used by Objective-C compilation actions. This is disabled by default
# because under some circumstances Clang module cache corruption can cause the
# Swift compiler to crash (sometimes when switching configurations or syncing a
# repository), but disabling it also causes a noticeable build time regression
# so it can be explicitly re-enabled by users who are not affected by those
# crashes.
'--features=swift.use_global_module_cache',
# https://docs.bazel.build/versions/master/command-line-reference.html
# Print the subcommand details in case of failure.
'--verbose_failures',
]
self.common_build_args = [
# https://github.com/bazelbuild/rules_swift
# If enabled and whole module optimisation is being used, the `*.swiftdoc`,
# `*.swiftmodule` and `*-Swift.h` are generated with a separate action
# rather than as part of the compilation.
'--features=swift.split_derived_files_generation',
# https://github.com/bazelbuild/rules_swift
# If enabled the skip function bodies frontend flag is passed when using derived
# files generation.
'--features=swift.skip_function_bodies_for_derived_files',
# Set the number of parallel processes to match the available CPU core count.
'--jobs={}'.format(os.cpu_count()),
]
self.common_debug_args = [
# https://github.com/bazelbuild/rules_swift
# If enabled, Swift compilation actions will use batch mode by passing
# `-enable-batch-mode` to `swiftc`. This is a new compilation mode as of
# Swift 4.2 that is intended to speed up non-incremental non-WMO builds by
# invoking a smaller number of frontend processes and passing them batches of
# source files.
'--features=swift.enable_batch_mode',
# https://docs.bazel.build/versions/master/command-line-reference.html
# Set the number of parallel jobs per module to saturate the available CPU resources.
'--swiftcopt=-j{}'.format(os.cpu_count() - 1),
]
self.common_release_args = [
# https://github.com/bazelbuild/rules_swift
# Enable whole module optimization.
'--features=swift.opt_uses_wmo',
# https://github.com/bazelbuild/rules_swift
# Use -Osize instead of -O when building swift modules.
'--features=swift.opt_uses_osize',
# --num-threads 0 forces swiftc to generate one object file per module; it:
# 1. resolves issues with the linker caused by the swift-objc mixing.
# 2. makes the resulting binaries significantly smaller (up to 9% for this project).
'--swiftcopt=-num-threads', '--swiftcopt=0',
# Strip unsused code.
'--features=dead_strip',
'--objc_enable_binary_stripping',
# Always embed bitcode into Watch binaries. This is required by the App Store.
'--apple_bitcode=watchos=embedded',
]
def add_remote_cache(self, host):
self.remote_cache = host
def add_cache_dir(self, path):
self.cache_dir = path
def add_additional_args(self, additional_args):
self.additional_args = additional_args
def set_build_number(self, build_number):
self.build_number = build_number
def set_configuration_path(self, path):
self.configuration_path = path
def set_configuration(self, configuration):
if configuration == 'debug_arm64':
self.configuration_args = [
# bazel debug build configuration
'-c', 'dbg',
# Build single-architecture binaries. It is almost 2 times faster is 32-bit support is not required.
'--ios_multi_cpus=arm64',
# Always build universal Watch binaries.
'--watchos_cpus=armv7k,arm64_32'
] + self.common_debug_args
elif configuration == 'release_arm64':
self.configuration_args = [
# bazel optimized build configuration
'-c', 'opt',
# Build single-architecture binaries. It is almost 2 times faster is 32-bit support is not required.
'--ios_multi_cpus=arm64',
# Always build universal Watch binaries.
'--watchos_cpus=armv7k,arm64_32'
] + self.common_release_args
elif configuration == 'release':
self.configuration_args = [
# bazel optimized build configuration
'-c', 'opt',
# Build universal binaries.
'--ios_multi_cpus=armv7,arm64',
# Always build universal Watch binaries.
'--watchos_cpus=armv7k,arm64_32'
# Generate DSYM files when building.
'--apple_generate_dsym',
# Require DSYM files as build output.
'--output_groups=+dsyms'
] + self.common_release_args
else:
raise Exception('Unknown configuration {}'.format(configuration))
def invoke_clean(self):
combined_arguments = [
self.build_environment.bazel_path,
'clean',
'--expunge'
]
print('TelegramBuild: running {}'.format(combined_arguments))
call_executable(combined_arguments)
def get_define_arguments(self):
return [
'--define=buildNumber={}'.format(self.build_number),
'--define=telegramVersion={}'.format(self.build_environment.app_version)
]
def get_project_generation_arguments(self):
combined_arguments = []
combined_arguments += self.common_args
combined_arguments += self.common_debug_args
combined_arguments += self.get_define_arguments()
if self.remote_cache is not None:
combined_arguments += [
'--remote_cache={}'.format(self.remote_cache),
'--experimental_remote_downloader="{}"'.format(self.remote_cache)
]
elif self.cache_dir is not None:
combined_arguments += [
'--disk_cache={path}'.format(path=self.cache_dir)
]
return combined_arguments
def invoke_build(self):
combined_arguments = [
self.build_environment.bazel_path,
'build',
'Telegram/Telegram'
]
if self.configuration_path is None:
raise Exception('configuration_path is not defined')
combined_arguments += [
'--override_repository=build_configuration={}'.format(self.configuration_path)
]
combined_arguments += self.common_args
combined_arguments += self.common_build_args
combined_arguments += self.get_define_arguments()
if self.remote_cache is not None:
combined_arguments += [
'--remote_cache={}'.format(self.remote_cache),
'--experimental_remote_downloader="{}"'.format(self.remote_cache)
]
elif self.cache_dir is not None:
combined_arguments += [
'--disk_cache={path}'.format(path=self.cache_dir)
]
combined_arguments += self.configuration_args
print('TelegramBuild: running {}'.format(combined_arguments))
call_executable(combined_arguments)
def clean(arguments):
bazel_command_line = BazelCommandLine(
bazel_path=arguments.bazel,
bazel_x86_64_path=None,
override_bazel_version=arguments.overrideBazelVersion,
override_xcode_version=arguments.overrideXcodeVersion
)
bazel_command_line.invoke_clean()
def resolve_configuration(bazel_command_line: BazelCommandLine, arguments):
if arguments.configurationGenerator is not None:
configuration_generator_arguments = shlex.split(arguments.configurationGenerator)
configuration_generator_executable = resolve_executable(configuration_generator_arguments[0])
if configuration_generator_executable is None:
print('{} is not a valid executable'.format(configuration_generator_arguments[0]))
exit(1)
temp_configuration_path = tempfile.mkdtemp()
resolved_configuration_generator_arguments = [configuration_generator_executable]
resolved_configuration_generator_arguments += configuration_generator_arguments[1:]
resolved_configuration_generator_arguments += [temp_configuration_path]
call_executable(resolved_configuration_generator_arguments, use_clean_environment=False)
print('TelegramBuild: using generated configuration in {}'.format(temp_configuration_path))
bazel_command_line.set_configuration_path(temp_configuration_path)
elif arguments.configurationPath is not None:
absolute_configuration_path = os.path.abspath(arguments.configurationPath)
if not os.path.isdir(absolute_configuration_path):
print('Error: {} does not exist'.format(absolute_configuration_path))
exit(1)
bazel_command_line.set_configuration_path(absolute_configuration_path)
else:
raise Exception('Neither configurationPath nor configurationGenerator are set')
def generate_project(arguments):
bazel_command_line = BazelCommandLine(
bazel_path=arguments.bazel,
bazel_x86_64_path=arguments.bazel_x86_64,
override_bazel_version=arguments.overrideBazelVersion,
override_xcode_version=arguments.overrideXcodeVersion
)
if arguments.cacheDir is not None:
bazel_command_line.add_cache_dir(arguments.cacheDir)
elif arguments.cacheHost is not None:
bazel_command_line.add_remote_cache(arguments.cacheDir)
resolve_configuration(bazel_command_line, arguments)
bazel_command_line.set_build_number(arguments.buildNumber)
disable_extensions = False
if arguments.disableExtensions is not None:
disable_extensions = arguments.disableExtensions
call_executable(['killall', 'Xcode'], check_result=False)
generate(
build_environment=bazel_command_line.build_environment,
disable_extensions=disable_extensions,
configuration_path=bazel_command_line.configuration_path,
bazel_app_arguments=bazel_command_line.get_project_generation_arguments()
)
def build(arguments):
bazel_command_line = BazelCommandLine(
bazel_path=arguments.bazel,
bazel_x86_64_path=None,
override_bazel_version=arguments.overrideBazelVersion,
override_xcode_version=arguments.overrideXcodeVersion
)
if arguments.cacheDir is not None:
bazel_command_line.add_cache_dir(arguments.cacheDir)
elif arguments.cacheHost is not None:
bazel_command_line.add_remote_cache(arguments.cacheDir)
resolve_configuration(bazel_command_line, arguments)
bazel_command_line.set_configuration(arguments.configuration)
bazel_command_line.set_build_number(arguments.buildNumber)
bazel_command_line.invoke_build()
def add_project_and_build_common_arguments(current_parser: argparse.ArgumentParser):
group = current_parser.add_mutually_exclusive_group(required=True)
group.add_argument(
'--configurationPath',
help='''
Path to a folder containing build configuration and provisioning profiles.
See build-system/example-configuration for an example.
''',
metavar='path'
)
group.add_argument(
'--configurationGenerator',
help='''
A command line invocation that will dynamically generate the configuration data
(project constants and provisioning profiles).
The expression will be parsed according to the shell parsing rules into program and arguments parts.
The program will be then invoked with the given arguments plus the path to the output directory.
See build-system/generate-configuration.sh for an example.
Example: --configurationGenerator="sh ~/my_script.sh argument1"
''',
metavar='command'
)
if __name__ == '__main__':
parser = argparse.ArgumentParser(prog='Make')
parser.add_argument(
'--verbose',
action='store_true',
default=False,
help='Print debug info'
)
parser.add_argument(
'--bazel',
required=True,
help='Use custom bazel binary',
metavar='path'
)
parser.add_argument(
'--overrideBazelVersion',
action='store_true',
help='Override bazel version with the actual version reported by the bazel binary'
)
parser.add_argument(
'--overrideXcodeVersion',
action='store_true',
help='Override xcode version with the actual version reported by \'xcode-select -p\''
)
parser.add_argument(
'--bazelArguments',
required=False,
help='Add additional arguments to all bazel invocations.',
metavar='arguments'
)
cacheTypeGroup = parser.add_mutually_exclusive_group()
cacheTypeGroup.add_argument(
'--cacheHost',
required=False,
help='Use remote build artifact cache to speed up rebuilds (See https://github.com/buchgr/bazel-remote).',
metavar='http://host:9092'
)
cacheTypeGroup.add_argument(
'--cacheDir',
required=False,
help='Cache build artifacts in a local directory to speed up rebuilds.',
metavar='path'
)
subparsers = parser.add_subparsers(dest='commandName', help='Commands')
cleanParser = subparsers.add_parser(
'clean', help='''
Clean local bazel cache. Does not affect files cached remotely (via --cacheHost=...) or
locally in an external directory ('--cacheDir=...')
'''
)
generateProjectParser = subparsers.add_parser('generateProject', help='Generate Xcode project')
if is_apple_silicon():
generateProjectParser.add_argument(
'--bazel_x86_64',
required=True,
help='A standalone bazel x86_64 binary is required to generate a project on Apple Silicon.',
metavar='path'
)
generateProjectParser.add_argument(
'--buildNumber',
required=False,
type=int,
default=10000,
help='Build number.',
metavar='number'
)
add_project_and_build_common_arguments(generateProjectParser)
generateProjectParser.add_argument(
'--disableExtensions',
action='store_true',
default=False,
help='''
The generated project will not include app extensions.
This allows Xcode to properly index the source code.
'''
)
buildParser = subparsers.add_parser('build', help='Build the app')
buildParser.add_argument(
'--buildNumber',
required=True,
type=int,
help='Build number.',
metavar='number'
)
add_project_and_build_common_arguments(buildParser)
buildParser.add_argument(
'--configuration',
choices=[
'debug_arm64',
'release_arm64',
'release_universal'
],
required=True,
help='Build configuration'
)
if len(sys.argv) < 2:
parser.print_help()
sys.exit(1)
args = parser.parse_args()
if args.verbose:
print(args)
if args.commandName is None:
exit(0)
try:
if args.commandName == 'clean':
clean(arguments=args)
elif args.commandName == 'generateProject':
generate_project(arguments=args)
elif args.commandName == 'build':
build(arguments=args)
else:
raise Exception('Unknown command')
except KeyboardInterrupt:
pass

View File

@ -0,0 +1,155 @@
import json
import os
import shutil
from BuildEnvironment import is_apple_silicon, call_executable, BuildEnvironment
def remove_directory(path):
if os.path.isdir(path):
shutil.rmtree(path)
def generate(build_environment: BuildEnvironment, disable_extensions, configuration_path, bazel_app_arguments):
project_path = os.path.join(build_environment.base_path, 'build-input/gen/project')
app_target = 'Telegram'
'''
TULSI_APP="build-input/gen/project/Tulsi.app"
TULSI="$TULSI_APP/Contents/MacOS/Tulsi"
rm -rf "$GEN_DIRECTORY/${APP_TARGET}.tulsiproj"
rm -rf "$TULSI_APP"
'''
os.makedirs(project_path, exist_ok=True)
remove_directory('{}/Tulsi.app'.format(project_path))
remove_directory('{project}/{target}.tulsiproj'.format(project=project_path, target=app_target))
tulsi_path = os.path.join(project_path, 'Tulsi.app/Contents/MacOS/Tulsi')
if is_apple_silicon():
tulsi_build_bazel_path = build_environment.bazel_x86_64_path
if tulsi_build_bazel_path is None or not os.path.isfile(tulsi_build_bazel_path):
print('Could not find a valid bazel x86_64 binary at {}'.format(tulsi_build_bazel_path))
exit(1)
else:
tulsi_build_bazel_path = build_environment.bazel_path
current_dir = os.getcwd()
os.chdir(os.path.join(build_environment.base_path, 'build-system/tulsi'))
call_executable([
tulsi_build_bazel_path,
'build', '//:tulsi',
'--xcode_version={}'.format(build_environment.xcode_version),
'--use_top_level_targets_for_symlinks',
'--verbose_failures'
])
os.chdir(current_dir)
bazel_wrapper_path = os.path.abspath('build-input/gen/project/bazel')
bazel_wrapper_arguments = []
bazel_wrapper_arguments += ['--override_repository=build_configuration={}'.format(configuration_path)]
if disable_extensions and False:
bazel_wrapper_arguments += ['--//Telegram:disableExtensions']
with open(bazel_wrapper_path, 'wb') as bazel_wrapper:
bazel_wrapper.write('''#!/bin/sh
{bazel} "$@" {arguments}
'''.format(
bazel=build_environment.bazel_path,
arguments=' '.join(bazel_wrapper_arguments)
).encode('utf-8'))
call_executable(['chmod', '+x', bazel_wrapper_path])
call_executable([
'unzip', '-oq',
'build-system/tulsi/bazel-bin/tulsi.zip',
'-d', project_path
])
user_defaults_path = os.path.expanduser('~/Library/Preferences/com.google.Tulsi.plist')
if os.path.isfile(user_defaults_path):
os.unlink(user_defaults_path)
with open(user_defaults_path, 'wb') as user_defaults:
user_defaults.write('''
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>defaultBazelURL</key>
<string>{}</string>
</dict>
</plist>
'''.format(bazel_wrapper_path).encode('utf-8'))
bazel_build_arguments = []
bazel_build_arguments += ['--override_repository=build_configuration={}'.format(configuration_path)]
if disable_extensions:
bazel_build_arguments += ['--//Telegram:disableExtensions']
call_executable([
tulsi_path,
'--',
'--verbose',
'--create-tulsiproj', app_target,
'--workspaceroot', './',
'--bazel', bazel_wrapper_path,
'--outputfolder', project_path,
'--target', '{target}:{target}'.format(target=app_target),
'--build-options', ' '.join(bazel_build_arguments)
])
additional_arguments = []
additional_arguments += ['--override_repository=build_configuration={}'.format(configuration_path)]
additional_arguments += bazel_app_arguments
if disable_extensions:
additional_arguments += ['--//Telegram:disableExtensions']
additional_arguments_string = ' '.join(additional_arguments)
tulsi_config_path = 'build-input/gen/project/{target}.tulsiproj/Configs/{target}.tulsigen'.format(target=app_target)
with open(tulsi_config_path, 'rb') as tulsi_config:
tulsi_config_json = json.load(tulsi_config)
for category in ['BazelBuildOptionsDebug', 'BazelBuildOptionsRelease']:
tulsi_config_json['optionSet'][category]['p'] += ' {}'.format(additional_arguments_string)
tulsi_config_json['sourceFilters'] = [
'Telegram/...',
'submodules/...',
'third-party/...'
]
with open(tulsi_config_path, 'wb') as tulsi_config:
tulsi_config.write(json.dumps(tulsi_config_json, indent=2).encode('utf-8'))
call_executable([
tulsi_path,
'--',
'--verbose',
'--genconfig', '{project}/{target}.tulsiproj:{target}'.format(project=project_path, target=app_target),
'--bazel', bazel_wrapper_path,
'--outputfolder', project_path,
'--no-open-xcode'
])
xcodeproj_path = '{project}/{target}.xcodeproj'.format(project=project_path, target=app_target)
bazel_build_settings_path = '{}/.tulsi/Scripts/bazel_build_settings.py'.format(xcodeproj_path)
with open(bazel_build_settings_path, 'rb') as bazel_build_settings:
bazel_build_settings_contents = bazel_build_settings.read().decode('utf-8')
bazel_build_settings_contents = bazel_build_settings_contents.replace(
'BUILD_SETTINGS = BazelBuildSettings(',
'import os\nBUILD_SETTINGS = BazelBuildSettings('
)
bazel_build_settings_contents = bazel_build_settings_contents.replace(
'\'--cpu=ios_arm64\'',
'\'--cpu=ios_arm64\'.replace(\'ios_arm64\', \'ios_sim_arm64\' if os.environ.get(\'EFFECTIVE_PLATFORM_NAME\') '
'== \'-iphonesimulator\' else \'ios_arm64\')'
)
with open(bazel_build_settings_path, 'wb') as bazel_build_settings:
bazel_build_settings.write(bazel_build_settings_contents.encode('utf-8'))
call_executable(['open', xcodeproj_path])

View File

@ -1 +0,0 @@
3.7.0

View File

@ -0,0 +1,11 @@
exports_files([
"Intents.mobileprovision",
"NotificationContent.mobileprovision",
"NotificationService.mobileprovision",
"Share.mobileprovision",
"Telegram.mobileprovision",
"WatchApp.mobileprovision",
"WatchExtension.mobileprovision",
"Widget.mobileprovision",
])

View File

@ -0,0 +1,10 @@
telegram_bundle_id = "ph.telegra.Telegraph"
telegram_api_id = "8"
telegram_api_hash = "7245de8e747a0d6fbe11f7cc14fcc0bb"
telegram_team_id = "C67CF9S4VU"
telegram_app_center_id = "0"
telegram_is_internal_build = "false"
telegram_is_appstore_build = "true"
telegram_appstore_id = "0"
telegram_app_specific_url_scheme = "tg"
telegram_aps_environment = "production"

View File

@ -0,0 +1,7 @@
#!/bin/sh
if [ ! -d "$1" ]; then
exit 1
fi
cp -R build-system/example-configuration/* "$1/"

View File

@ -1,129 +0,0 @@
#!/bin/bash
set -e
FASTLANE="$(which fastlane)"
EXPECTED_VARIABLES=(\
APPLE_ID \
BASE_BUNDLE_ID \
APP_NAME \
TEAM_ID \
PROVISIONING_DIRECTORY \
)
MISSING_VARIABLES="0"
for VARIABLE_NAME in ${EXPECTED_VARIABLES[@]}; do
if [ "${!VARIABLE_NAME}" = "" ]; then
echo "$VARIABLE_NAME not defined"
MISSING_VARIABLES="1"
fi
done
if [ "$MISSING_VARIABLES" == "1" ]; then
exit 1
fi
if [ ! -d "$PROVISIONING_DIRECTORY" ]; then
echo "Directory $PROVISIONING_DIRECTORY does not exist"
exit 1
fi
BASE_DIR=$(mktemp -d)
FASTLANE_DIR="$BASE_DIR/fastlane"
mkdir "$FASTLANE_DIR"
FASTFILE="$FASTLANE_DIR/Fastfile"
touch "$FASTFILE"
CREDENTIALS=(\
--username "$APPLE_ID" \
--team_id "$TEAM_ID" \
)
export FASTLANE_SKIP_UPDATE_CHECK=1
APP_EXTENSIONS=(\
Share \
SiriIntents \
NotificationContent \
NotificationService \
Widget \
)
echo "lane :manage_app do" >> "$FASTFILE"
echo " produce(" >> "$FASTFILE"
echo " username: '$APPLE_ID'," >> "$FASTFILE"
echo " app_identifier: '${BASE_BUNDLE_ID}'," >> "$FASTFILE"
echo " app_name: '$APP_NAME'," >> "$FASTFILE"
echo " language: 'English'," >> "$FASTFILE"
echo " app_version: '1.0'," >> "$FASTFILE"
echo " team_id: '$TEAM_ID'," >> "$FASTFILE"
echo " skip_itc: true," >> "$FASTFILE"
echo " )" >> "$FASTFILE"
echo " produce(" >> "$FASTFILE"
echo " username: '$APPLE_ID'," >> "$FASTFILE"
echo " app_identifier: '${BASE_BUNDLE_ID}.watchkitapp'," >> "$FASTFILE"
echo " app_name: '$APP_NAME Watch App'," >> "$FASTFILE"
echo " language: 'English'," >> "$FASTFILE"
echo " app_version: '1.0'," >> "$FASTFILE"
echo " team_id: '$TEAM_ID'," >> "$FASTFILE"
echo " skip_itc: true," >> "$FASTFILE"
echo " )" >> "$FASTFILE"
echo " produce(" >> "$FASTFILE"
echo " username: '$APPLE_ID'," >> "$FASTFILE"
echo " app_identifier: '${BASE_BUNDLE_ID}.watchkitapp.watchkitextension'," >> "$FASTFILE"
echo " app_name: '$APP_NAME Watch App Extension'," >> "$FASTFILE"
echo " language: 'English'," >> "$FASTFILE"
echo " app_version: '1.0'," >> "$FASTFILE"
echo " team_id: '$TEAM_ID'," >> "$FASTFILE"
echo " skip_itc: true," >> "$FASTFILE"
echo " )" >> "$FASTFILE"
for EXTENSION in ${APP_EXTENSIONS[@]}; do
echo " produce(" >> "$FASTFILE"
echo " username: '$APPLE_ID'," >> "$FASTFILE"
echo " app_identifier: '${BASE_BUNDLE_ID}.${EXTENSION}'," >> "$FASTFILE"
echo " app_name: '${APP_NAME} ${EXTENSION}'," >> "$FASTFILE"
echo " language: 'English'," >> "$FASTFILE"
echo " app_version: '1.0'," >> "$FASTFILE"
echo " team_id: '$TEAM_ID'," >> "$FASTFILE"
echo " skip_itc: true," >> "$FASTFILE"
echo " )" >> "$FASTFILE"
done
echo "end" >> "$FASTFILE"
pushd "$BASE_DIR"
fastlane cert ${CREDENTIALS[@]} --development
fastlane manage_app
fastlane produce group -g "group.$BASE_BUNDLE_ID" -n "$APP_NAME Group" ${CREDENTIALS[@]}
fastlane produce enable_services -a "$BASE_BUNDLE_ID" ${CREDENTIALS[@]} \
--app-group \
--push-notification \
--sirikit
fastlane produce associate_group -a "$BASE_BUNDLE_ID" "group.$BASE_BUNDLE_ID" ${CREDENTIALS[@]}
for EXTENSION in ${APP_EXTENSIONS[@]}; do
fastlane produce enable_services -a "${BASE_BUNDLE_ID}.${EXTENSION}" ${CREDENTIALS[@]} \
--app-group
fastlane produce associate_group -a "${BASE_BUNDLE_ID}.${EXTENSION}" "group.$BASE_BUNDLE_ID" ${CREDENTIALS[@]}
done
for DEVELOPMENT_FLAG in "--development"; do
fastlane sigh -a "$BASE_BUNDLE_ID" ${CREDENTIALS[@]} -o "$PROVISIONING_DIRECTORY" $DEVELOPMENT_FLAG \
--skip_install
for EXTENSION in ${APP_EXTENSIONS[@]}; do
fastlane sigh -a "${BASE_BUNDLE_ID}.${EXTENSION}" ${CREDENTIALS[@]} -o "$PROVISIONING_DIRECTORY" $DEVELOPMENT_FLAG \
--skip_install
done
done
popd
rm -rf "$BASE_DIR"

@ -1 +1 @@
Subproject commit b965114f31a464185318c71ef3d0c1538d0c52de
Subproject commit ee28952fc91b493b5e1d11e4ccf12d7df4454504

View File

@ -1 +0,0 @@
12.2

5
versions.json Normal file
View File

@ -0,0 +1,5 @@
{
"app": "7.3",
"bazel": "3.7.0",
"xcode": "12.3"
}