import os import json import shutil import subprocess from build import * from pathlib import Path as SysPath from cache import Cache from env import Environment from platform import Platform from target import Target from path import Path class GenericBuildSystem(BuildSystem): def __init__(self, **kwargs): self.__data = kwargs.get('data', None) super().__init__(**kwargs) def __get_watched_files(self): result = [] ns = self.get_path_namespaces() if 'watch_files' in self.__data: watch_list = self.__data['watch_files'] for p in watch_list: path = Path(p) real_paths = path.expand_path(relative_to=ns) for p2 in real_paths: result.append(p2) manifest_path = os.path.join(self.binary_dir(), 'compile_commands.json') manifest_file = None manifest = None try: manifest_file = open(manifest_path, mode='r') except: return result try: manifest = json.load(manifest_file) except: return result for v in manifest: if 'file' not in v: continue path = v['file'] result.append(path) return result def __get_mtime(self): files = self.__get_watched_files() result = 0 for path in files: mtime = os.path.getmtime(path) if mtime > result: result = mtime return result def _is_configuration_out_of_date(self): return False def _is_build_out_of_date(self): current_mtime = self.__get_mtime() target_mtime = Cache.get(f'component.{self.name()}.build-mtime') if target_mtime is None: return True if current_mtime > target_mtime: return True for d in self.parent().collect_dependencies(): build_system = d.build_system() if build_system is None: continue if build_system.is_build_out_of_date() or build_system.is_configuration_out_of_date(): return True return False def __run_command(self, name, **kwargs): verbose = kwargs.get('verbose', False) ns = self.get_path_namespaces() stdout = None if not verbose: stdout = subprocess.DEVNULL cmd = self.__data.get(name, None) if cmd is None: return args = cmd.get('args', None) if args is None: raise BuildConfigurationError(f'{self.name()} is incorrectly configured. build_command has no args defined') expanded_args = [] for p in args: parts = p.split(':') if len(parts) < 2 or parts[0] not in ns: expanded_args.append(p) continue paths = Path(p).expand_path(relative_to=ns) expanded_args.extend(paths) result = subprocess.run(expanded_args, stdout=stdout) if result.returncode != 0: raise BuildConfigurationError(f'Execution of {name} for {self.name()} failed. See log for details') def configure(self, **kwargs): self.__run_command('configure_command', **kwargs) def build(self, **kwargs): self.__run_command('build_command', **kwargs) def install(self, **kwargs): self.install_from_seed() previous_mtime = Cache.get(f'component.{self.name()}.build-mtime') if previous_mtime is None: previous_mtime = 0 new_mtime = self.__get_mtime() if new_mtime > previous_mtime: Cache.set(f'component.{self.name()}.build-mtime', new_mtime)