aboutsummaryrefslogtreecommitdiffstats
path: root/build/scripts/ios_wrapper.py
diff options
context:
space:
mode:
authoralexv-smirnov <alex@ydb.tech>2023-06-13 11:05:01 +0300
committeralexv-smirnov <alex@ydb.tech>2023-06-13 11:05:01 +0300
commitbf0f13dd39ee3e65092ba3572bb5b1fcd125dcd0 (patch)
tree1d1df72c0541a59a81439842f46d95396d3e7189 /build/scripts/ios_wrapper.py
parent8bfdfa9a9bd19bddbc58d888e180fbd1218681be (diff)
downloadydb-bf0f13dd39ee3e65092ba3572bb5b1fcd125dcd0.tar.gz
add ymake export to ydb
Diffstat (limited to 'build/scripts/ios_wrapper.py')
-rw-r--r--build/scripts/ios_wrapper.py180
1 files changed, 180 insertions, 0 deletions
diff --git a/build/scripts/ios_wrapper.py b/build/scripts/ios_wrapper.py
new file mode 100644
index 0000000000..d3aa48387a
--- /dev/null
+++ b/build/scripts/ios_wrapper.py
@@ -0,0 +1,180 @@
+import errno
+import json
+import os
+import shutil
+import subprocess
+import sys
+import tarfile
+import plistlib
+
+
+def ensure_dir(path):
+ try:
+ os.makedirs(path)
+ except OSError as e:
+ if e.errno != errno.EEXIST or not os.path.isdir(path):
+ raise
+
+
+def just_do_it(args):
+ if not args:
+ raise Exception('Not enough args!')
+ parts = [[]]
+ for arg in args:
+ if arg == '__DELIM__':
+ parts.append([])
+ else:
+ parts[-1].append(arg)
+ if len(parts) != 3 or len(parts[0]) != 5:
+ raise Exception('Bad call')
+ bin_name, ibtool_path, main_out, app_name, module_dir = parts[0]
+ bin_name = os.path.basename(bin_name)
+ inputs, storyboard_user_flags = parts[1:]
+ plists, storyboards, signs, nibs, resources, signed_resources, plist_jsons, strings = [], [], [], [], [], [], [], []
+ for i in inputs:
+ if i.endswith('.plist') or i.endswith('.partial_plist'):
+ plists.append(i)
+ elif i.endswith('.compiled_storyboard_tar'):
+ storyboards.append(i)
+ elif i.endswith('.xcent'):
+ signs.append(i)
+ elif i.endswith('.nib'):
+ nibs.append(i)
+ elif i.endswith('.resource_tar'):
+ resources.append(i)
+ elif i.endswith('.signed_resource_tar'):
+ signed_resources.append(i)
+ elif i.endswith('.plist_json'):
+ plist_jsons.append(i)
+ elif i.endswith('.strings_tar'):
+ strings.append(i)
+ else:
+ print >> sys.stderr, 'Unknown input:', i, 'ignoring'
+ if not plists:
+ raise Exception("Can't find plist files")
+ if not plists[0].endswith('.plist'):
+ print >> sys.stderr, "Main plist file can be defined incorretly"
+ if not storyboards:
+ print >> sys.stderr, "Storyboards list are empty"
+ if len(signs) > 1:
+ raise Exception("Too many .xcent files")
+ app_dir = os.path.join(module_dir, app_name + '.app')
+ ensure_dir(app_dir)
+ copy_nibs(nibs, module_dir, app_dir)
+ replaced_parameters = {
+ 'DEVELOPMENT_LANGUAGE': 'en',
+ 'EXECUTABLE_NAME': bin_name,
+ 'PRODUCT_BUNDLE_IDENTIFIER': 'Yandex.' + app_name,
+ 'PRODUCT_NAME': app_name,
+ }
+ replaced_templates = {}
+ for plist_json in plist_jsons:
+ with open(plist_json) as jsonfile:
+ for k, v in json.loads(jsonfile.read()).items():
+ replaced_parameters[k] = v
+ for k, v in replaced_parameters.items():
+ replaced_templates['$(' + k + ')'] = v
+ replaced_templates['${' + k + '}'] = v
+ make_main_plist(plists, os.path.join(app_dir, 'Info.plist'), replaced_templates)
+ link_storyboards(ibtool_path, storyboards, app_name, app_dir, storyboard_user_flags)
+ if resources:
+ extract_resources(resources, app_dir)
+ if signed_resources:
+ extract_resources(signed_resources, app_dir, sign=True)
+ if strings:
+ extract_resources(strings, app_dir, strings=True)
+ if not signs:
+ sign_file = os.path.join(module_dir, app_name + '.xcent')
+ with open(sign_file, 'w') as f:
+ f.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>com.apple.security.get-task-allow</key>
+ <true/>
+</dict>
+</plist>
+ ''')
+ else:
+ sign_file = signs[0]
+ sign_application(sign_file, app_dir)
+ make_archive(app_dir, main_out)
+
+
+def is_exe(fpath):
+ return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
+
+
+def copy_nibs(nibs, module_dir, app_dir):
+ for nib in nibs:
+ dst = os.path.join(app_dir, os.path.relpath(nib, module_dir))
+ ensure_dir(os.path.dirname(dst))
+ shutil.copyfile(nib, dst)
+
+
+def make_main_plist(inputs, out, replaced_parameters):
+ united_data = {}
+ for i in inputs:
+ united_data.update(plistlib.readPlist(i))
+
+ def scan_n_replace(root):
+ if not isinstance(root, dict):
+ raise Exception('Invalid state')
+ for k in root:
+ if isinstance(root[k], list):
+ for i in xrange(len(root[k])):
+ if isinstance(root[k][i], dict):
+ scan_n_replace(root[k][i])
+ elif root[k][i] in replaced_parameters:
+ root[k][i] = replaced_parameters[root[k][i]]
+ elif isinstance(root[k], dict):
+ scan_n_replace(root[k])
+ else:
+ if root[k] in replaced_parameters:
+ root[k] = replaced_parameters[root[k]]
+ scan_n_replace(united_data)
+ plistlib.writePlist(united_data, out)
+ subprocess.check_call(['/usr/bin/plutil', '-convert', 'binary1', out])
+
+
+def link_storyboards(ibtool, archives, app_name, app_dir, flags):
+ unpacked = []
+ for arc in archives:
+ unpacked.append(os.path.splitext(arc)[0] + 'c')
+ ensure_dir(unpacked[-1])
+ with tarfile.open(arc) as a:
+ a.extractall(path=unpacked[-1])
+ flags += [
+ '--module', app_name,
+ '--link', app_dir,
+ ]
+ subprocess.check_call([ibtool] + flags +
+ ['--errors', '--warnings', '--notices', '--output-format', 'human-readable-text'] +
+ unpacked)
+
+
+def sign_application(xcent, app_dir):
+ subprocess.check_call(['/usr/bin/codesign', '--force', '--sign', '-', '--entitlements', xcent, '--timestamp=none', app_dir])
+
+
+def extract_resources(resources, app_dir, strings=False, sign=False):
+ for res in resources:
+ with tarfile.open(res) as tf:
+ for tfinfo in tf:
+ tf.extract(tfinfo.name, app_dir)
+ if strings:
+ subprocess.check_call(['/usr/bin/plutil', '-convert', 'binary1', os.path.join(app_dir, tfinfo.name)])
+ if sign:
+ subprocess.check_call(['/usr/bin/codesign', '--force', '--sign', '-', os.path.join(app_dir, tfinfo.name)])
+
+
+def make_archive(app_dir, output):
+ with tarfile.open(output, "w") as tar_handle:
+ for root, _, files in os.walk(app_dir):
+ for f in files:
+ tar_handle.add(os.path.join(root, f), arcname=os.path.join(os.path.basename(app_dir),
+ os.path.relpath(os.path.join(root, f), app_dir)))
+
+
+if __name__ == '__main__':
+ just_do_it(sys.argv[1:])