meta: add sources from prototype meadow build system
This commit is contained in:
@@ -0,0 +1,316 @@
|
||||
import os
|
||||
import json
|
||||
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 CMakeBuildSystem(BuildSystem):
|
||||
def __init__(self, **kwargs):
|
||||
name = kwargs.get('name', None)
|
||||
source_dir = kwargs.get('source_dir', None)
|
||||
bin_dir = kwargs.get('bin_dir', None)
|
||||
parent = kwargs.get('parent', None)
|
||||
self.__data = kwargs.get('data', None)
|
||||
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
def build_for(self):
|
||||
if self.__data is None or 'build_for' not in self.__data:
|
||||
return 'target'
|
||||
return self.__data['build_for']
|
||||
|
||||
|
||||
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_build_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 __get_configure_mtime(self):
|
||||
source_dir = os.path.abspath(self.source_dir())
|
||||
result = 0
|
||||
for root, dirs, files in os.walk(source_dir):
|
||||
for f in files:
|
||||
if f != 'CMakeLists.txt' and not f.endswith('.cmake'):
|
||||
continue
|
||||
|
||||
target_path = os.path.join(root, f)
|
||||
mtime = os.path.getmtime(target_path)
|
||||
if mtime > result:
|
||||
result = mtime
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def _is_configuration_out_of_date(self):
|
||||
cache_file = os.path.join(self.binary_dir(), 'CMakeCache.txt')
|
||||
if not os.path.isfile(cache_file):
|
||||
return True
|
||||
|
||||
current_mtime = self.__get_configure_mtime()
|
||||
target_mtime = Cache.get(f'component.{self.name()}.configure-mtime')
|
||||
if target_mtime is None:
|
||||
target_mtime = 0
|
||||
|
||||
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 _is_build_out_of_date(self):
|
||||
current_mtime = self.__get_build_mtime()
|
||||
target_mtime = Cache.get(f'component.{self.name()}.build-mtime')
|
||||
if target_mtime is None:
|
||||
target_mtime = 0
|
||||
|
||||
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 __get_published_items(self):
|
||||
published = {}
|
||||
|
||||
for d in self.parent().collect_dependencies():
|
||||
build_sys = d.build_system()
|
||||
ns = {}
|
||||
if build_sys is not None:
|
||||
ns = build_sys.get_path_namespaces()
|
||||
|
||||
p = d.publish()
|
||||
if p is None:
|
||||
continue
|
||||
|
||||
path = p.path()
|
||||
if path is not None:
|
||||
if 'path' not in published:
|
||||
published['path'] = []
|
||||
|
||||
path = Path.expand_all(path, relative_to=ns)
|
||||
published['path'].extend(path)
|
||||
|
||||
cmake = p.cmake()
|
||||
if cmake is not None:
|
||||
if 'cmake' not in published:
|
||||
published['cmake'] = {}
|
||||
|
||||
if 'module_paths' in cmake:
|
||||
if 'module_paths' not in published['cmake']:
|
||||
published['cmake']['module_paths'] = []
|
||||
|
||||
module_paths = cmake['module_paths']
|
||||
module_paths = Path.expand_all(module_paths, relative_to=ns)
|
||||
published['cmake']['module_paths'].extend(module_paths)
|
||||
|
||||
return published
|
||||
|
||||
|
||||
def configure(self, **kwargs):
|
||||
verbose = kwargs.get('verbose', False)
|
||||
ns = self.get_path_namespaces()
|
||||
stdout = None
|
||||
if not verbose:
|
||||
stdout = subprocess.DEVNULL
|
||||
|
||||
target = Target.current_target()
|
||||
platform = Platform.current_platform()
|
||||
cmake_platform = platform.get_component('cmake')
|
||||
cmake_args = [
|
||||
'cmake',
|
||||
'-DCMAKE_EXPORT_COMPILE_COMMANDS=ON',
|
||||
'--no-warn-unused-cli'
|
||||
]
|
||||
|
||||
if 'configure_args' in self.__data:
|
||||
cmake_args.extend(self.__data['configure_args'])
|
||||
|
||||
published = self.__get_published_items()
|
||||
env = os.environ.copy()
|
||||
if 'path' in published:
|
||||
path = ''
|
||||
if 'PATH' in env:
|
||||
path = env['PATH']
|
||||
|
||||
if len(path):
|
||||
path += ':'
|
||||
|
||||
path += ':'.join(published['path'])
|
||||
env['PATH'] = path
|
||||
|
||||
module_paths = []
|
||||
if 'cmake' in published:
|
||||
cmake_publish = published['cmake']
|
||||
for p in cmake_publish.get('module_paths', []):
|
||||
path = Path(p)
|
||||
for p2 in path.expand_path(relative_to=ns):
|
||||
module_paths.append(p2)
|
||||
|
||||
install_details = self.parent().install()
|
||||
install_prefix = ''
|
||||
if self.build_for() == 'host':
|
||||
install_prefix = Environment.native_root()
|
||||
cmake_platform = None
|
||||
seed_install_prefix = '/'
|
||||
if install_details is not None:
|
||||
seed_install_prefix = install_details.get('prefix', seed_install_prefix)
|
||||
seed_install_prefix = Path(seed_install_prefix).remove_root().get_path()
|
||||
install_prefix = os.path.join(install_prefix, seed_install_prefix)
|
||||
else:
|
||||
install_prefix = Environment.system_root()
|
||||
env['ROSETTA_SYSROOT'] = Environment.system_root()
|
||||
|
||||
seed_install_prefix = target.install_prefix()
|
||||
if install_details is not None:
|
||||
seed_install_prefix = install_details.get('prefix', seed_install_prefix)
|
||||
seed_install_prefix = Path(seed_install_prefix).remove_root().get_path()
|
||||
install_prefix = os.path.join(install_prefix, seed_install_prefix)
|
||||
|
||||
cmake_args.append(f'-DCMAKE_INSTALL_PREFIX={install_prefix}')
|
||||
|
||||
if cmake_platform is not None:
|
||||
if 'module_paths' in cmake_platform:
|
||||
for p in cmake_platform['module_paths']:
|
||||
module_paths.append(os.path.join(platform.base_directory(), p))
|
||||
if 'toolchain_file' in cmake_platform:
|
||||
toolchain_file = os.path.join(platform.base_directory(), cmake_platform['toolchain_file'])
|
||||
cmake_args.append(f'-DCMAKE_TOOLCHAIN_FILE={toolchain_file}')
|
||||
if 'system_name' in cmake_platform:
|
||||
cmake_args.append(f'-DCMAKE_SYSTEM_NAME={cmake_platform['system_name']}')
|
||||
|
||||
if 'module_paths' in self.__data:
|
||||
for p in self.__data['module_paths']:
|
||||
path = Path(p)
|
||||
for p2 in path.expand_path(relative_to=ns):
|
||||
module_paths.append(p2)
|
||||
|
||||
if len(module_paths) > 0:
|
||||
cmake_args.append(f'-DCMAKE_MODULE_PATH={';'.join(module_paths)}')
|
||||
|
||||
source_dir = os.path.abspath(self.source_dir())
|
||||
bin_dir = os.path.abspath(self.binary_dir())
|
||||
cmake_args.append(source_dir)
|
||||
|
||||
SysPath(bin_dir).mkdir(parents=True, exist_ok=True)
|
||||
result = subprocess.run(cmake_args, cwd=bin_dir, env=env, stdout=stdout)
|
||||
|
||||
if result.returncode == 0:
|
||||
Cache.set(f'component.{self.name()}.configure-mtime', self.__get_configure_mtime())
|
||||
else:
|
||||
raise BuildConfigurationError(f'CMake configuration for {self.name()} failed. See log for details')
|
||||
|
||||
|
||||
def __find_build_command(self):
|
||||
bin_dir = os.path.abspath(self.binary_dir())
|
||||
if os.path.isfile(os.path.join(bin_dir, 'build.ninja')):
|
||||
return 'ninja'
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def build(self, **kwargs):
|
||||
verbose = kwargs.get('verbose', False)
|
||||
stdout = None
|
||||
if not verbose:
|
||||
stdout = subprocess.DEVNULL
|
||||
|
||||
bin_dir = os.path.abspath(self.binary_dir())
|
||||
build_cmd = self.__find_build_command()
|
||||
if build_cmd is None:
|
||||
raise BuildError(f'Cannot determine which command to use to build {self.name()}')
|
||||
|
||||
env = os.environ.copy()
|
||||
if self.build_for() != 'host':
|
||||
env['ROSETTA_SYSROOT'] = Environment.system_root()
|
||||
|
||||
args = [ build_cmd ]
|
||||
result = subprocess.run(args, cwd=bin_dir, stdout=stdout, env=env)
|
||||
|
||||
if result.returncode != 0:
|
||||
raise BuildConfigurationError(f'{build_cmd} build for {self.name()} failed. See log for details')
|
||||
|
||||
|
||||
def install(self, **kwargs):
|
||||
self.install_from_seed()
|
||||
|
||||
verbose = kwargs.get('verbose', False)
|
||||
stdout = None
|
||||
if not verbose:
|
||||
stdout = subprocess.DEVNULL
|
||||
|
||||
bin_dir = os.path.abspath(self.binary_dir())
|
||||
build_cmd = self.__find_build_command()
|
||||
if build_cmd is None:
|
||||
raise BuildError(f'Cannot determine which command to use to build {self.name()}')
|
||||
|
||||
args = [ build_cmd, 'install' ]
|
||||
result = subprocess.run(args, cwd=bin_dir, stdout=stdout)
|
||||
|
||||
if result.returncode == 0:
|
||||
Cache.set(f'component.{self.name()}.build-mtime', self.__get_build_mtime())
|
||||
Reference in New Issue
Block a user