From b6ef418a07aa88abddfac2e32eea08f83964e604 Mon Sep 17 00:00:00 2001 From: Sergey Kopytov Date: Thu, 12 Sep 2019 22:35:27 +0300 Subject: [PATCH] add configs generator script --- xcode/config_generator/Readme.md | 3 + xcode/config_generator/gen_configurations.py | 94 ++++++++++++++++++ xcode/config_generator/render_xcconfigs.rb | 98 +++++++++++++++++++ xcode/config_generator/settings.json | 25 +++++ .../config_generator/target_xcconfig.mustache | 7 ++ 5 files changed, 227 insertions(+) create mode 100644 xcode/config_generator/Readme.md create mode 100644 xcode/config_generator/gen_configurations.py create mode 100644 xcode/config_generator/render_xcconfigs.rb create mode 100644 xcode/config_generator/settings.json create mode 100644 xcode/config_generator/target_xcconfig.mustache diff --git a/xcode/config_generator/Readme.md b/xcode/config_generator/Readme.md new file mode 100644 index 0000000..77fe832 --- /dev/null +++ b/xcode/config_generator/Readme.md @@ -0,0 +1,3 @@ +# Генератор конфигурационных файлов в формате `.xcconfig` + + здесь должна быть инструкция или ссылка на нее \ No newline at end of file diff --git a/xcode/config_generator/gen_configurations.py b/xcode/config_generator/gen_configurations.py new file mode 100644 index 0000000..22845ed --- /dev/null +++ b/xcode/config_generator/gen_configurations.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from __future__ import unicode_literals # python 2/3 support + +from itertools import chain +import json + +distribution_options = ["Enterprise", "Standard"] +server_type_options = ["Mock", "Touchin", "Customer"] +server_environment_options = ["Dev", "Test", "Stage", "Prod"] +ssl_pinning_options = ["WithSSLPinning", "WithoutSSLPinning"] +build_type_options = ["Debug", "Release"] + +all_options = [ + distribution_options, + server_type_options, + server_environment_options, + ssl_pinning_options, + build_type_options +] + +def combine_string_with_options(all_options, string="", applied_options=[]): + if len(all_options) == 0: + yield string, applied_options + return + + for current_option in chain.from_iterable(all_options[:1]): + for result_tuple in combine_string_with_options(all_options[1:], string + current_option, applied_options + [current_option]): + yield result_tuple + + yield ("AppStoreRelease", ['AppStore', 'Customer', 'Prod', 'WithSSLPinning', 'Release']) + +def make_config_dict(args): + config_name, applied_options = args + + if "Enterprise" in applied_options: + account_type = "Enterprise" + elif "Standard" in applied_options: + account_type = "Standard" + else: + account_type = "AppStore" + + if "Debug" in applied_options: + build_type = "debug" + elif "AppStore" in applied_options: + build_type = "appstore" + else: + build_type = "release" + + return { + "name": config_name, + "build_type": build_type, + "account_type": account_type, + "xcconfig_options": [ + { + "key": "SWIFT_ACTIVE_COMPILATION_CONDITIONS", + "value": " ".join(map(lambda option: option.upper(), applied_options)) + }, + { + "key": "DEBUG_INFORMATION_FORMAT", + "value": "dwarf" if "Debug" in applied_options else "dwarf-with-dsym" + }, + { + "key": "VALIDATE_PRODUCT", + "value": "NO" if "Debug" in applied_options else "YES" + }, + { + "key": "ENABLE_TESTABILITY", + "value": "YES" if "Debug" in applied_options else "NO" + }, + { + "key": "CODE_SIGN_IDENTITY", + "value": "iPhone Developer" if account_type == "Standard" else "iPhone Distribution" + }, + { + "key": "GCC_OPTIMIZATION_LEVEL", + "value": "0" if "Debug" in applied_options else "s" + }, + { + "key": "SWIFT_OPTIMIZATION_LEVEL", + "value": "-Onone" if "Debug" in applied_options else "-O" + }, + { + "key": "SWIFT_COMPILATION_MODE", + "value": "singlefile" if "Debug" in applied_options else "wholemodule" + } + ] + } + + +config_dicts = map(make_config_dict, combine_string_with_options(all_options)) + +print(json.dumps({"configurations": config_dicts}, indent=4)) diff --git a/xcode/config_generator/render_xcconfigs.rb b/xcode/config_generator/render_xcconfigs.rb new file mode 100644 index 0000000..750a2e7 --- /dev/null +++ b/xcode/config_generator/render_xcconfigs.rb @@ -0,0 +1,98 @@ +require 'json' +require 'mustache' + + +# create config files if needed +system("touch configs_data.json") unless File.exist?("configs_data") +system("mkdir TargetConfigurations") unless Dir.exist?("TargetConfigurations") + +# call python script and generate configs to config file +system("python gen_configurations.py > configs_data.json") + + +# open settings + template file +settings = JSON.load(File.open("settings.json")) +target_xcconfig_tempate = File.read("target_xcconfig.mustache") + + +# set global property +targets = settings["targets"] + +# make tuple of key and value become mustache template element +def config_option(key, value) + return { "key" => key, "value" => value } +end + +# return empty array or generated dev team hash +def development_team_if_needed(properties, account_type) + development_team_key = "DEVELOPMENT_TEAM" + if properties.key?(development_team_key) + return [] + end + + team_value = account_type == "Standard" ? "D4HA43V467" : "228J5MMU7S" + return [config_option(development_team_key, team_value)] +end + +# return empty array or generated provisioning profile hash +def provisioning_profile_if_needed(properties, account_type) + provisioning_key = "PROVISIONING_PROFILE_SPECIFIER" + if properties.key?(provisioning_key) + return [] + end + + bundle_id = properties["PRODUCT_BUNDLE_IDENTIFIER"] + if account_type == "AppStore" + app_store_profiile = "match AppStore " + bundle_id + return [config_option(provisioning_key, app_store_profiile)] + else + return [config_option(provisioning_key, bundle_id)] + end +end + +# generate missing properties if needed +def generate_missing_properties(properties, account_type) + result = [] + result.concat(development_team_if_needed(properties, account_type)) + result.concat(provisioning_profile_if_needed(properties, account_type)) + return result +end + +# run through all target in project +targets.each do |target| + + # need open everytime, because script make some changes only for this target + configs = JSON.load(File.open("configs_data.json"))["configurations"] + + # run through all configs + configs.each do |config| + + # take default values + account_type = config["account_type"] + target_name = target.keys.first + properties = target[target_name][account_type] + + # add properties from settings file + properties.each do |key, value| + config["xcconfig_options"].append(config_option(key, value)) + end + + # add missing properties if needed + config["xcconfig_options"].concat(generate_missing_properties(properties, account_type)) + + # create settings pack + config_data = { + "target_name": target_name, + "configuration": config + } + + # create file for every setting in loop + File.open("TargetConfigurations/" + target_name + config["name"] + ".xcconfig", 'w') { |file| + file.puts(Mustache.render(target_xcconfig_tempate, config_data)) + } + end + +end + +# remove config file, it's trash +system("rm configs_data.json") if File.exist?("configs_data.json") diff --git a/xcode/config_generator/settings.json b/xcode/config_generator/settings.json new file mode 100644 index 0000000..d70867d --- /dev/null +++ b/xcode/config_generator/settings.json @@ -0,0 +1,25 @@ +{ + "targets": [ + { + "target_name": { + "Standard": { + "PROVISIONING_PROFILE_SPECIFIER": "", + "PRODUCT_BUNDLE_IDENTIFIER": "", + "CODE_SIGN_ENTITLEMENTS": "" + }, + + "Enterprise": { + "PROVISIONING_PROFILE_SPECIFIER": "", + "PRODUCT_BUNDLE_IDENTIFIER": "", + "CODE_SIGN_ENTITLEMENTS": "" + }, + + "AppStore": { + "DEVELOPMENT_TEAM": "", + "PRODUCT_BUNDLE_IDENTIFIER": "", + "CODE_SIGN_ENTITLEMENTS": "" + } + } + } + ] +} diff --git a/xcode/config_generator/target_xcconfig.mustache b/xcode/config_generator/target_xcconfig.mustache new file mode 100644 index 0000000..7e5477a --- /dev/null +++ b/xcode/config_generator/target_xcconfig.mustache @@ -0,0 +1,7 @@ +#include "Pods/Target Support Files/Pods-{{target_name}}/Pods-{{target_name}}.{{configuration.build_type}}.xcconfig" + +{{#configuration.xcconfig_options}} +{{key}} = {{value}} +{{/configuration.xcconfig_options}} + +CODE_SIGN_STYLE = Manual \ No newline at end of file