diff --git a/base/__init__.py b/base/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/base/run_command.py b/base/run_command.py new file mode 100644 index 0000000..d6f61e0 --- /dev/null +++ b/base/run_command.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python +import subprocess +import re + +class MessageType: + STATUS = 1 + MESSAGE = 2 + +class Message(object): + def __init__(self, message, type): + self.message_ = message + self.type_ = type + + def message(self): + return self.message_ + + def type(self): + return self.type_ + +class Policy(object): + def __init__(self, cb): + self.progress_ = 0.0 + self.cb_ = cb + + def process(self, message): + if self.cb_: + self.cb_(self.progress_, message) + + def update_progress_message(self, progress, message): + self.progress_ = progress + self.process(Message(message, MessageType.STATUS)) + +class CommonPolicy(Policy): + def __init__(self, cb): + Policy.__init__(self, cb) + +class CmakePolicy(Policy): + def __init__(self, cb): + Policy.__init__(self, cb) + + def process(self, message): + self.progress_ += 1.0 + super(CmakePolicy, self).process(message) + + def update_progress_message(self, progress, message): + super(CmakePolicy, self).update_progress_message(progress, message) + +class MakePolicy(Policy): + def __init__(self, cb): + Policy.__init__(self, cb) + + def process(self, message): + if message.type() != MessageType.MESSAGE: + super(MakePolicy, self).process(message) + return + + cur = self.parse_message_to_get_percent(message.message()) + if not cur: + return + + self.progress_ = cur + super(MakePolicy, self).process(message) + + def update_progress_message(self, progress, message): + super(MakePolicy, self).update_progress_message(progress, message) + + def parse_message_to_get_percent(self, message): + if not message: + return None + + res = re.search(r'\A\[ (\d+)%\]', message) + if res != None: + return float(res.group(1)) + + return None + +class NinjaPolicy(Policy): + def __init__(self, cb): + Policy.__init__(self, cb) + + def process(self, message): + if message.type() != MessageType.MESSAGE: + super(NinjaPolicy, self).process(message) + return + + cur,total = self.parse_message_to_get_range(message.message()) + if not cur and not total: + return + + self.progress_ = cur / total * 100.0 + super(NinjaPolicy, self).process(message) + + def update_progress_message(self, progress, message): + super(NinjaPolicy, self).update_progress_message(progress, message) + + def parse_message_to_get_range(self, message): + if not message: + return None, None + + res = re.search(r'\A\[(\d+)/(\d+)\]', message) + if res != None: + return float(res.group(1)), float(res.group(2)) + + return None, None + +def run_command_cb(cmd, policy): + if not policy: + policy = Policy + try: + policy.update_progress_message(0.0, 'Command {0} started'.format(cmd)) + process = subprocess.Popen(cmd, stdout=subprocess.PIPE) + while True: + output = process.stdout.readline() + if output == '' and process.poll() is not None: + break + if output: + line = output.strip() + policy.process(Message(line, MessageType.MESSAGE)) + rc = process.poll() + policy.update_progress_message(100.0, 'Command {0} finished successfully'.format(cmd)) + except subprocess.CalledProcessError as ex: + policy.update_progress_message(100.0, 'Command {0} finished with exception {1}'.format(cmd, str(ex))) + raise ex + + return rc \ No newline at end of file diff --git a/base/system_info.py b/base/system_info.py new file mode 100644 index 0000000..44093e0 --- /dev/null +++ b/base/system_info.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python + +import platform +import re + +class Architecture(object): + def __init__(self, arch_str, bit, default_install_prefix_path): + self.name_ = arch_str + self.bit_ = bit + self.default_install_prefix_path_ = default_install_prefix_path + + def name(self): + return self.name_ + + def bit(self): + return self.bit_ + + def default_install_prefix_path(self): + return self.default_install_prefix_path_ + +class Platform(object): + def __init__(self, name, arch, package_types): + self.name_ = name + self.arch_ = arch + self.package_types_ = package_types + + def name(self): + return self.name_ + + def arch(self): + return self.arch_ + + def package_types(self): + return self.package_types_ + +class SupportedPlatform(object): + def __init__(self, name, archs, package_types): + self.name_ = name + self.archs_ = archs + self.package_types_ = package_types + + def name(self): + return self.name_ + + def archs(self): + return self.archs_ + + def package_types(self): + return self.package_types_ + + def architecture_by_arch(self, arch): + for curr_arch in self.archs_: + if (curr_arch.name == arch): + return curr_arch + + return None + + def architecture_by_bit(self, arch_bit): + for curr_arch in self.archs_: + if (curr_arch.bit() == arch_bit): + return curr_arch + + return None + +SUPPORTED_PLATFORMS = [SupportedPlatform('linux', [Architecture('x86_64', 64, '/usr/local'), Architecture('i386', 32, '/usr/local')], ['DEB', 'RPM', 'TGZ']), + SupportedPlatform('windows', [Architecture('x86_64', 64, '/mingw64'), Architecture('i386', 32, '/mingw32')], ['NSIS', 'ZIP']), + SupportedPlatform('macosx', [Architecture('x86_64', 64, '/usr/local')], ['DragNDrop', 'ZIP']), + SupportedPlatform('freebsd', [Architecture('x86_64', 64, '/usr/local')], ['TGZ']), + SupportedPlatform('android', [Architecture('armv7', 32, '/opt/android-ndk/platforms/android-9/arch-arm/usr/')], ['APK'])] + +def get_extension_by_package(package_type): + if package_type == 'DEB': + return 'deb' + elif package_type == 'RPM': + return 'rpm' + elif package_type == 'TGZ': + return 'tar.gz' + elif package_type == 'NSIS': + return 'exe' + elif package_type == 'ZIP': + return 'zip' + elif package_type == 'DragNDrop': + return 'dmg' + elif package_type == 'APK': + return 'apk' + else: + return None + +def get_os(): + uname_str = platform.system() + if 'MINGW' in uname_str: + return 'windows' + elif uname_str == 'Windows': + return 'windows' + elif uname_str == 'Linux': + return 'linux' + elif uname_str == 'Darwin': + return 'macosx' + elif uname_str == 'FreeBSD': + return 'freebsd' + elif uname_str == 'Android': + return 'android' + else: + return None + +def get_arch_bit(): + arch = platform.architecture() + return re.search(r'\d+', arch[0]).group() + +def get_supported_platform_by_name(platform): + return next((x for x in SUPPORTED_PLATFORMS if x.name() == platform), None) + +def gen_routing_key(platform, arch): + return platform + '_' + arch + +class BuildSystem: + def __init__(self, name, cmd_line, cmake_generator_arg): + self.name_ = name + self.cmd_line_ = cmd_line + self.cmake_generator_arg_ = cmake_generator_arg + + def cmake_generator_arg(self): + return self.cmake_generator_arg_ + + def name(self): + return self.name_ + + def cmd_line(self): # cmd + args + return self.cmd_line_ + +SUPPORTED_BUILD_SYSTEMS = [BuildSystem('ninja', ['ninja'], '-GNinja'), + BuildSystem('make', ['make', '-j2'], '-GUnix Makefiles'), + BuildSystem('gmake', ['gmake', '-j2'], '-GUnix Makefiles')] + +def get_supported_build_system_by_name(name): + return next((x for x in SUPPORTED_BUILD_SYSTEMS if x.name() == name), None) diff --git a/base/utils.py b/base/utils.py new file mode 100644 index 0000000..19b0e0f --- /dev/null +++ b/base/utils.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python + +import os + +class BuildError(Exception): + def __init__(self, value): + self.value_ = value + def __str__(self): + return self.value_ + +def read_file_line_by_line(file): + if not os.path.exists(file): + raise BuildError('file path: %s not exists' % file) + + file_array = [] + with open(file, "r") as ins: + for line in ins: + file_array.append(line.strip()) + + return file_array \ No newline at end of file