Last active
July 3, 2020 05:50
-
-
Save xnorpx/6e1262a80785fc81326f6511fa7faafe to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import sys | |
import logging | |
import itertools | |
from ruamel.yaml import YAML # Github actions needs yaml 1.2 | |
build_settings = ['disable_intrinsics', 'fixed_point', 'custom_modes'] | |
platforms = ['win', 'linux', 'mac', 'ios', 'android'] | |
archs = ['x86', 'x86_64', 'armv7', 'arm64'] | |
# TODO: Add support for custom scrips add hock scripts | |
# TODO: Add support to figure out number of cores/ht on machine and use with -j | |
# TODO: Add support for gitlab | |
# TODO: Add support for automake | |
# TODO: Add build support for ios, android, linux arm | |
# TODO: Add test support for linux arm (qemu) | |
# TODO: Add support for cpp check | |
# TODO: Code coverage? | |
def main(): | |
import argparse | |
parser = argparse.ArgumentParser(description='') | |
parser.add_argument('--log-level', dest='log_level', default='info', help='logging level', | |
choices=['debug', 'info', 'warning', 'error', 'critical']) | |
args = parser.parse_args() | |
logging.basicConfig(format='%(asctime)s %(levelname)-8s [%(pathname)s,%(lineno)d] %(message)s', | |
level=getattr(logging, args.log_level.upper()), | |
stream=sys.stdout) | |
logging.info('Start') | |
configs = generate_configs() | |
cmake_transformer = CMakeTransformer() | |
cmake_configs = cmake_transformer.transform(configs) | |
github_actions_transformer = GithubActionsTransformer() | |
github_action_configs = github_actions_transformer.transform(cmake_configs) | |
github_action_yaml_file = 'build.yml' | |
save_yaml_file(github_action_configs, github_action_yaml_file) | |
logging.info("Generated file {} with {} configs".format( | |
github_action_yaml_file, len(cmake_configs))) | |
logging.info('Stop') | |
def generate_configs(): | |
logging.info('Generate configs') | |
configs = [] | |
combinations = list(itertools.product( | |
[False, True], repeat=len(build_settings))) | |
for combination in combinations: | |
for platform in platforms: | |
for arch in archs: | |
config = {} | |
config['configurations'] = dict( | |
zip(build_settings, combination)) | |
config['arch'] = arch | |
config['platform'] = platform | |
configs.append(config) | |
return configs | |
class Transformer(): | |
def __init__(self): | |
super(Transformer, self).__init__() | |
def transform(self, item): | |
assert False | |
class CMakeTransformer(Transformer): | |
def __init__(self): | |
super(CMakeTransformer, self).__init__() | |
self.cmake_build = {'win': {'x86_64': True, 'x86': True, 'armv7': True, 'arm64': True}, | |
'linux': {'x86_64': True}, 'mac': {'x86_64': True}} | |
self.cmake_test = {'win': {'x86_64': True, 'x86': True}, 'linux': { | |
'x86_64': True}, 'mac': {'x86_64': True}} | |
self.cmake_platform_build_options = {'win': { | |
'x86_64': '-G "Visual Studio 16 2019" -A x64', | |
'x86': '-G "Visual Studio 16 2019" -A Win32', | |
'armv7': '-G "Visual Studio 16 2019" -A ARM', | |
'arm64': '-G "Visual Studio 16 2019" -A ARM64'}} | |
def transform(self, configs): | |
cmake_configs = [] | |
for config in configs: | |
if self._supported_build_target(config['platform'], config['arch']): | |
d = {} | |
d['configure'] = self._add_config_step(config) | |
d['build'] = 'cmake --build . --config Release' | |
d['name'] = self._generate_name(config) | |
d['host'] = config['platform'] | |
if self._supported_test_target(config['platform'], config['arch']): | |
d['test'] = 'ctest' | |
cmake_configs.append(d) | |
return cmake_configs | |
def _generate_name(self, config): | |
name = config['platform'] + '-' + config['arch'] | |
for key, value in config['configurations'].items(): | |
name = name + '-' + key + '-' + ('on' if value else 'off') | |
return name | |
def _supported_build_target(self, platform, arch): | |
try: | |
return self.cmake_build[platform][arch] | |
except: | |
return False | |
def _supported_test_target(self, platform, arch): | |
try: | |
return self.cmake_test[platform][arch] | |
except: | |
return False | |
def _platform_build_option(self, platform, arch): | |
try: | |
return " " + self.cmake_platform_build_options[platform][arch] | |
except: | |
return "" | |
def _add_config_step(self, config): | |
configure = 'cmake .. -DOPUS_BUILD_PROGRAMS=ON -DOPUS_BUILD_TESTING=ON' | |
for key, value in config['configurations'].items(): | |
configure += ' -DOPUS_' + key.upper() + '=' + ('ON' if value else 'OFF') | |
configure += self._platform_build_option( | |
config['platform'], config['arch']) | |
return configure | |
class GithubActionsTransformer(Transformer): | |
def __init__(self): | |
super(GithubActionsTransformer, self).__init__() | |
self.actions = { | |
'on': [ | |
"push", | |
"pull_request" | |
], | |
"jobs": { | |
}, | |
"name": "Opus Build Matrix" | |
} | |
self.host = { | |
'win': 'windows-latest', | |
'linux': 'ubuntu-latest', | |
'android': 'ubuntu-latest', | |
'mac': 'macos-latest', | |
'ios': 'macos-latest'} | |
self.workdir = 'build' | |
def transform(self, configs): | |
for config in configs: | |
job = self._create_job(config) | |
self.actions['jobs'][config['name']] = job | |
return self.actions | |
def _create_job(self, config): | |
job = {} | |
job['name'] = config['name'] | |
job['runs-on'] = self.host[config['host']] | |
job['steps'] = [ | |
{ | |
"uses": "actions/checkout@v2", | |
"with": { | |
"fetch-depth": 0 | |
} | |
}, { | |
"run": "mkdir {}".format(self.workdir), | |
"name": "Create Work Dir" | |
}, | |
{ | |
"working-directory": "{}".format(self.workdir), | |
"run": "{}".format(config['configure']), | |
"name": "Configure" | |
}, | |
{ | |
"working-directory": "{}".format(self.workdir), | |
"run": "{}".format(config['build']), | |
"name": "Build" | |
}, | |
] | |
if 'test' in config: | |
job['steps'].append( | |
{ | |
"working-directory": "{}".format(self.workdir), | |
"run": "{}".format(config['test']), | |
"name": "Test" | |
} | |
) | |
return job | |
def save_yaml_file(d, yaml_file): | |
yaml = YAML() | |
yaml.default_flow_style = False | |
with open(yaml_file, 'w') as outfile: | |
yaml.dump(d, outfile) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment