mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-05 19:28:46 +02:00
Build system
This commit is contained in:
parent
25d13682ba
commit
7ed08c0141
15 changed files with 173 additions and 18 deletions
9
.bazelrc
9
.bazelrc
|
|
@ -22,6 +22,15 @@ build --spawn_strategy=standalone
|
|||
build --strategy=SwiftCompile=standalone
|
||||
build --define RULES_SWIFT_BUILD_DUMMY_WORKER=1
|
||||
|
||||
build:swift_profile --jobs=1
|
||||
build:swift_profile --local_cpu_resources=1
|
||||
build:swift_profile --features=-swift.enable_batch_mode
|
||||
build:swift_profile --experimental_ui_max_stdouterr_bytes=104857600
|
||||
build:swift_profile --@build_bazel_rules_swift//swift:copt=-Xfrontend
|
||||
build:swift_profile --@build_bazel_rules_swift//swift:copt=-debug-time-function-bodies
|
||||
build:swift_profile --@build_bazel_rules_swift//swift:copt=-Xfrontend
|
||||
build:swift_profile --@build_bazel_rules_swift//swift:copt=-debug-time-expression-type-checking
|
||||
|
||||
common:index_build --experimental_convenience_symlinks=ignore
|
||||
common:index_build --bes_backend= --bes_results_url=
|
||||
common:index_build --nolegacy_important_outputs
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -77,3 +77,4 @@ spm-files
|
|||
xcode-files
|
||||
.bsp/**
|
||||
/.claude/
|
||||
/buildbox/*
|
||||
|
|
|
|||
|
|
@ -5,40 +5,165 @@ import shutil
|
|||
import tempfile
|
||||
import plistlib
|
||||
import argparse
|
||||
import subprocess
|
||||
import base64
|
||||
|
||||
from BuildEnvironment import run_executable_with_output, check_run_system
|
||||
|
||||
|
||||
def get_certificate_base64():
|
||||
certificate_data = run_executable_with_output('security', arguments=['find-certificate', '-c', 'Apple Distribution: Telegram FZ-LLC (C67CF9S4VU)', '-p'])
|
||||
certificate_data = certificate_data.replace('-----BEGIN CERTIFICATE-----', '')
|
||||
certificate_data = certificate_data.replace('-----END CERTIFICATE-----', '')
|
||||
certificate_data = certificate_data.replace('\n', '')
|
||||
return certificate_data
|
||||
def setup_temp_keychain(p12_path, p12_password=''):
|
||||
"""Create a temporary keychain and import the p12 certificate."""
|
||||
keychain_name = 'generate-profiles-temp.keychain'
|
||||
keychain_password = 'temp123'
|
||||
|
||||
# Delete if exists
|
||||
run_executable_with_output('security', arguments=['delete-keychain', keychain_name], check_result=False)
|
||||
|
||||
# Create keychain
|
||||
run_executable_with_output('security', arguments=[
|
||||
'create-keychain', '-p', keychain_password, keychain_name
|
||||
], check_result=True)
|
||||
|
||||
# Add to search list
|
||||
existing = run_executable_with_output('security', arguments=['list-keychains', '-d', 'user'])
|
||||
run_executable_with_output('security', arguments=[
|
||||
'list-keychains', '-d', 'user', '-s', keychain_name, existing.replace('"', '')
|
||||
], check_result=True)
|
||||
|
||||
# Unlock and set settings
|
||||
run_executable_with_output('security', arguments=['set-keychain-settings', keychain_name])
|
||||
run_executable_with_output('security', arguments=[
|
||||
'unlock-keychain', '-p', keychain_password, keychain_name
|
||||
])
|
||||
|
||||
# Import p12
|
||||
run_executable_with_output('security', arguments=[
|
||||
'import', p12_path, '-k', keychain_name, '-P', p12_password,
|
||||
'-T', '/usr/bin/codesign', '-T', '/usr/bin/security'
|
||||
], check_result=True)
|
||||
|
||||
# Set partition list for access
|
||||
run_executable_with_output('security', arguments=[
|
||||
'set-key-partition-list', '-S', 'apple-tool:,apple:', '-k', keychain_password, keychain_name
|
||||
], check_result=True)
|
||||
|
||||
return keychain_name
|
||||
|
||||
|
||||
def process_provisioning_profile(source, destination, certificate_data):
|
||||
def cleanup_temp_keychain(keychain_name):
|
||||
"""Remove the temporary keychain."""
|
||||
run_executable_with_output('security', arguments=['delete-keychain', keychain_name], check_result=False)
|
||||
|
||||
|
||||
def get_signing_identity_from_p12(p12_path, p12_password=''):
|
||||
"""Extract the common name (signing identity) from the p12 certificate."""
|
||||
proc = subprocess.Popen(
|
||||
['openssl', 'pkcs12', '-in', p12_path, '-passin', 'pass:' + p12_password, '-nokeys', '-legacy'],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||
)
|
||||
cert_pem, _ = proc.communicate()
|
||||
|
||||
proc2 = subprocess.Popen(
|
||||
['openssl', 'x509', '-noout', '-subject', '-nameopt', 'oneline,-esc_msb'],
|
||||
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||
)
|
||||
subject, _ = proc2.communicate(cert_pem)
|
||||
subject = subject.decode('utf-8').strip()
|
||||
|
||||
# Parse CN from subject line like: subject= C = AE, O = ..., CN = Some Name
|
||||
if 'CN = ' in subject:
|
||||
cn = subject.split('CN = ')[-1].split(',')[0].strip()
|
||||
return cn
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def get_certificate_base64_from_p12(p12_path, p12_password=''):
|
||||
"""Extract the certificate as base64 from p12 file."""
|
||||
# Extract certificate in PEM format
|
||||
proc = subprocess.Popen(
|
||||
['openssl', 'pkcs12', '-in', p12_path, '-passin', 'pass:' + p12_password, '-nokeys', '-legacy'],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||
)
|
||||
cert_pem, _ = proc.communicate()
|
||||
|
||||
# Convert to DER format
|
||||
proc2 = subprocess.Popen(
|
||||
['openssl', 'x509', '-outform', 'DER'],
|
||||
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||
)
|
||||
cert_der, _ = proc2.communicate(cert_pem)
|
||||
|
||||
return base64.b64encode(cert_der).decode('utf-8')
|
||||
|
||||
|
||||
def process_provisioning_profile(source, destination, certificate_data, signing_identity, keychain_name):
|
||||
parsed_plist = run_executable_with_output('security', arguments=['cms', '-D', '-i', source], check_result=True)
|
||||
parsed_plist_file = tempfile.mktemp()
|
||||
with open(parsed_plist_file, 'w+') as file:
|
||||
file.write(parsed_plist)
|
||||
|
||||
run_executable_with_output('plutil', arguments=['-remove', 'DeveloperCertificates.0', parsed_plist_file])
|
||||
# Remove all existing developer certificates
|
||||
while True:
|
||||
result = run_executable_with_output('plutil', arguments=['-remove', 'DeveloperCertificates.0', parsed_plist_file], check_result=False)
|
||||
if result is None or 'Could not' in str(result) or result == '':
|
||||
# Check if the removal actually failed by trying to extract
|
||||
check = run_executable_with_output('plutil', arguments=['-extract', 'DeveloperCertificates.0', 'raw', parsed_plist_file], check_result=False)
|
||||
if check is None or 'Could not' in str(check):
|
||||
break
|
||||
|
||||
# Insert the new certificate
|
||||
run_executable_with_output('plutil', arguments=['-insert', 'DeveloperCertificates.0', '-data', certificate_data, parsed_plist_file])
|
||||
|
||||
# Remove the DER-Encoded-Profile (signature)
|
||||
run_executable_with_output('plutil', arguments=['-remove', 'DER-Encoded-Profile', parsed_plist_file])
|
||||
|
||||
run_executable_with_output('security', arguments=['cms', '-S', '-N', 'Apple Distribution: Telegram FZ-LLC (C67CF9S4VU)', '-i', parsed_plist_file, '-o', destination])
|
||||
# Sign with the certificate from the temporary keychain
|
||||
run_executable_with_output('security', arguments=[
|
||||
'cms', '-S', '-k', keychain_name, '-N', signing_identity, '-i', parsed_plist_file, '-o', destination
|
||||
], check_result=True)
|
||||
|
||||
os.unlink(parsed_plist_file)
|
||||
|
||||
|
||||
def generate_provisioning_profiles(source_path, destination_path):
|
||||
certificate_data = get_certificate_base64()
|
||||
def generate_provisioning_profiles(source_path, destination_path, certs_path):
|
||||
p12_path = os.path.join(certs_path, 'SelfSigned.p12')
|
||||
|
||||
if not os.path.exists(destination_path):
|
||||
print('{} does not exits'.format(destination_path))
|
||||
if not os.path.exists(p12_path):
|
||||
print('{} does not exist'.format(p12_path))
|
||||
sys.exit(1)
|
||||
|
||||
for file_name in os.listdir(source_path):
|
||||
if file_name.endswith('.mobileprovision'):
|
||||
process_provisioning_profile(source=source_path + '/' + file_name, destination=destination_path + '/' + file_name, certificate_data=certificate_data)
|
||||
if not os.path.exists(destination_path):
|
||||
print('{} does not exist'.format(destination_path))
|
||||
sys.exit(1)
|
||||
|
||||
# Extract certificate info from p12
|
||||
p12_password = '' # fake-codesigning uses empty password
|
||||
certificate_data = get_certificate_base64_from_p12(p12_path, p12_password)
|
||||
signing_identity = get_signing_identity_from_p12(p12_path, p12_password)
|
||||
|
||||
if not signing_identity:
|
||||
print('Could not extract signing identity from {}'.format(p12_path))
|
||||
sys.exit(1)
|
||||
|
||||
print('Using signing identity: {}'.format(signing_identity))
|
||||
|
||||
# Setup temporary keychain with the certificate
|
||||
keychain_name = setup_temp_keychain(p12_path, p12_password)
|
||||
|
||||
try:
|
||||
for file_name in os.listdir(source_path):
|
||||
if file_name.endswith('.mobileprovision'):
|
||||
print('Processing {}'.format(file_name))
|
||||
process_provisioning_profile(
|
||||
source=os.path.join(source_path, file_name),
|
||||
destination=os.path.join(destination_path, file_name),
|
||||
certificate_data=certificate_data,
|
||||
signing_identity=signing_identity,
|
||||
keychain_name=keychain_name
|
||||
)
|
||||
print('Done. Generated {} profiles.'.format(
|
||||
len([f for f in os.listdir(destination_path) if f.endswith('.mobileprovision')])
|
||||
))
|
||||
finally:
|
||||
cleanup_temp_keychain(keychain_name)
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ class BazelCommandLine:
|
|||
self.show_actions = False
|
||||
self.enable_sandbox = False
|
||||
self.disable_provisioning_profiles = False
|
||||
self.profile_swift = False
|
||||
|
||||
self.common_args = [
|
||||
# https://docs.bazel.build/versions/master/command-line-reference.html
|
||||
|
|
@ -143,6 +144,9 @@ class BazelCommandLine:
|
|||
def set_disable_provisioning_profiles(self):
|
||||
self.disable_provisioning_profiles = True
|
||||
|
||||
def set_profile_swift(self, value):
|
||||
self.profile_swift = value
|
||||
|
||||
def set_configuration(self, configuration):
|
||||
if configuration == 'debug_arm64':
|
||||
self.configuration_args = [
|
||||
|
|
@ -300,6 +304,8 @@ class BazelCommandLine:
|
|||
]
|
||||
|
||||
combined_arguments += self.configuration_args
|
||||
if self.profile_swift:
|
||||
combined_arguments += ['--config=swift_profile']
|
||||
|
||||
print('TelegramBuild: running')
|
||||
print(subprocess.list2cmdline(combined_arguments))
|
||||
|
|
@ -620,6 +626,7 @@ def build(bazel, arguments):
|
|||
bazel_command_line.set_continue_on_error(arguments.continueOnError)
|
||||
bazel_command_line.set_show_actions(arguments.showActions)
|
||||
bazel_command_line.set_enable_sandbox(arguments.sandbox)
|
||||
bazel_command_line.set_profile_swift(arguments.profileSwift)
|
||||
|
||||
bazel_command_line.set_split_swiftmodules(arguments.enableParallelSwiftmoduleGeneration)
|
||||
|
||||
|
|
@ -972,6 +979,12 @@ if __name__ == '__main__':
|
|||
help='Generate .swiftmodule files in parallel to building modules, can speed up compilation on multi-core '
|
||||
'systems. '
|
||||
)
|
||||
buildParser.add_argument(
|
||||
'--profileSwift',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Enable single-core Swift compile profiling flags.'
|
||||
)
|
||||
buildParser.add_argument(
|
||||
'--target',
|
||||
type=str,
|
||||
|
|
@ -1063,6 +1076,13 @@ if __name__ == '__main__':
|
|||
type=str,
|
||||
help='Path to the destination directory.'
|
||||
)
|
||||
generate_profiles_build_parser.add_argument(
|
||||
'--certsPath',
|
||||
required=False,
|
||||
type=str,
|
||||
default='build-system/fake-codesigning/certs',
|
||||
help='Path to the directory containing SelfSigned.p12 certificate.'
|
||||
)
|
||||
|
||||
remote_upload_testflight_parser = subparsers.add_parser('remote-deploy-testflight', help='Build the app using a remote environment.')
|
||||
remote_upload_testflight_parser.add_argument(
|
||||
|
|
@ -1304,7 +1324,7 @@ if __name__ == '__main__':
|
|||
additional_codesigning_output_path=remote_input_path
|
||||
)
|
||||
|
||||
GenerateProfiles.generate_provisioning_profiles(source_path=remote_input_path + '/profiles', destination_path=args.destination)
|
||||
GenerateProfiles.generate_provisioning_profiles(source_path=remote_input_path + '/profiles', destination_path=args.destination, certs_path=args.certsPath)
|
||||
elif args.commandName == 'remote-deploy-testflight':
|
||||
env = os.environ
|
||||
if 'APPSTORE_CONNECT_USERNAME' not in env:
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 21edd49ba4db756cc54b104b6b7eb7137801e8c4
|
||||
Subproject commit fb08c7e64a421df645dad8963f7f52a9af3f2ecb
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue