From 0961551fd8c1d9832a6d6b39a1df1d1ae59e63ca Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Thu, 22 Jul 2021 09:51:13 +0300 Subject: [PATCH] aedi: use pathlib module for most of path operations --- aedi/builder.py | 73 ++++++++++++------------- aedi/state.py | 57 ++++++++++---------- aedi/target/base.py | 73 +++++++++++++------------ aedi/target/library_tier1.py | 72 ++++++++++++------------- aedi/target/library_tier2.py | 102 +++++++++++++++++------------------ aedi/target/main.py | 44 ++++++++------- aedi/target/special.py | 32 +++++------ aedi/target/tools.py | 20 +++---- aedi/utility.py | 34 ++++++------ 9 files changed, 252 insertions(+), 255 deletions(-) diff --git a/aedi/builder.py b/aedi/builder.py index 8dfa64dd..0c57822a 100644 --- a/aedi/builder.py +++ b/aedi/builder.py @@ -19,6 +19,7 @@ import argparse import copy import os +from pathlib import Path from platform import machine import shutil import subprocess @@ -45,33 +46,29 @@ class Builder(object): state.platform = self._platforms[0] if arguments.source_path: - state.source_path = os.path.abspath(arguments.source_path) + state.source_path = Path(arguments.source_path).absolute() if arguments.target: self._target = self._targets[arguments.target] - state.source = state.source_path + self._target.name + os.sep + state.source = state.source_path / self._target.name state.external_source = False else: assert arguments.source - state.source = os.path.abspath(arguments.source) + os.sep + state.source = Path(arguments.source).absolute() state.external_source = True self._detect_target() del self._targets if arguments.build_path: - state.build_path = os.path.abspath(arguments.build_path) + state.build_path = Path(arguments.build_path).absolute() else: - state.build_path = state.root_path + 'build' + os.sep + self._target.name + \ - os.sep + ('xcode' if state.xcode else 'make') + state.build_path = state.root_path / 'build' / self._target.name / ('xcode' if state.xcode else 'make') if arguments.output_path: - state.output_path = os.path.abspath(arguments.output_path) + state.output_path = Path(arguments.output_path).absolute() else: - state.output_path = state.root_path + 'output' - - state.build_path += os.sep - state.output_path += os.sep + state.output_path = state.root_path / 'output' state.jobs = arguments.jobs and arguments.jobs or \ subprocess.check_output(['sysctl', '-n', 'hw.ncpu']).decode('ascii').strip() @@ -79,12 +76,12 @@ class Builder(object): def _populate_platforms(self, arguments): state = self._state - def adjust_sdk_path(path: str) -> str: + def adjust_sdk_path(path: Path) -> Path: if path: - return os.path.abspath(path) + return path.absolute() - sdk_probe_path = f'{state.root_path}sdk{os.sep}MacOSX{os_version}.sdk' - return sdk_probe_path if os.path.exists(sdk_probe_path) else None + sdk_probe_path = state.root_path / 'sdk' / f'MacOSX{os_version}.sdk' + return sdk_probe_path if sdk_probe_path.exists() else None if not arguments.disable_x64: os_version = arguments.os_version_x64 if arguments.os_version_x64 else OS_VERSION_X86_64 @@ -117,13 +114,13 @@ class Builder(object): target.prepare_source(state) if target.destination == Target.DESTINATION_DEPS: - state.install_path = state.deps_path + target.name + os.sep + state.install_path = state.deps_path / target.name elif target.destination == Target.DESTINATION_OUTPUT: - state.install_path = state.output_path + target.name + os.sep + state.install_path = state.output_path / target.name assert state.install_path - if not state.xcode and os.path.exists(state.install_path): + if not state.xcode and state.install_path.exists(): shutil.rmtree(state.install_path) if target.name != DOWNLOAD_CMAKE_TARGET_NAME: @@ -156,13 +153,13 @@ class Builder(object): continue state.platform = platform - state.build_path = base_build_path + 'build_' + platform.architecture + os.sep + state.build_path = base_build_path / ('build_' + platform.architecture) if platform.architecture == machine(): state.native_build_path = state.build_path target = copy.deepcopy(base_target) - state.install_path = base_build_path + 'install_' + platform.architecture + os.sep + state.install_path = base_build_path / ('install_' + platform.architecture) self._build(target) @@ -171,14 +168,14 @@ class Builder(object): Builder._merge_install_paths(install_paths, base_install_path) @staticmethod - def _compare_files(paths: typing.Sequence[str]) -> bool: + def _compare_files(paths: typing.Sequence[Path]) -> bool: content = None for path in paths: - if not os.path.exists(path): + if not path.exists(): return False - with open(path, 'rb') as f: + with path.open('rb') as f: if content: if content != f.read(): return False @@ -188,8 +185,8 @@ class Builder(object): return True @staticmethod - def _merge_file(src: os.DirEntry, src_sub_paths: typing.Sequence[str], dst_path: str): - with open(src.path, 'rb') as f: + def _merge_file(src: Path, src_sub_paths: typing.Sequence[Path], dst_path: Path): + with open(src, 'rb') as f: header = f.read(8) is_executable = header[:4] == b'\xcf\xfa\xed\xfe' @@ -197,7 +194,7 @@ class Builder(object): if is_executable or is_library: # Merge executable and library files - dst_file = dst_path + os.sep + src.name + dst_file = dst_path / src.name args = ['lipo'] args += src_sub_paths @@ -205,16 +202,16 @@ class Builder(object): subprocess.check_call(args) # Apply ad-hoc code signing on executable files outside of application bundles - if is_executable and '.app/Contents/' not in src.path: + if is_executable and '.app/Contents/' not in str(src): args = ('codesign', '--sign', '-', dst_file) subprocess.check_call(args) else: if not Builder._compare_files(src_sub_paths): - print(f'WARNING: Source files for {dst_path + os.sep + src.name} don\'t match') + print(f'WARNING: Source files for {dst_path / src.name} don\'t match') shutil.copy(src_sub_paths[0], dst_path) @staticmethod - def _merge_missing_files(src_paths: typing.Sequence[str], dst_path: str): + def _merge_missing_files(src_paths: typing.Sequence[Path], dst_path: Path): shifted_src_paths = [path for path in src_paths] last_path_index = len(src_paths) - 1 @@ -222,33 +219,33 @@ class Builder(object): shifted_src_paths.append(shifted_src_paths[0]) del shifted_src_paths[0] - if not os.path.exists(shifted_src_paths[0]): + if not shifted_src_paths[0].exists(): continue Builder._merge_install_paths(shifted_src_paths, dst_path, missing_files_only=True) @staticmethod - def _merge_install_paths(src_paths: typing.Sequence[str], dst_path: str, missing_files_only=False): + def _merge_install_paths(src_paths: typing.Sequence[Path], dst_path: Path, missing_files_only=False): if len(src_paths) == 0: return if not missing_files_only: - if os.path.exists(dst_path): + if dst_path.exists(): shutil.rmtree(dst_path) os.makedirs(dst_path, exist_ok=True) - for src in os.scandir(src_paths[0]): - src_sub_paths = [path + os.sep + src.name for path in src_paths] + for src in src_paths[0].iterdir(): + src_sub_paths = [path / src.name for path in src_paths] if src.is_dir(): - Builder._merge_install_paths(src_sub_paths, dst_path + os.sep + src.name, missing_files_only) + Builder._merge_install_paths(src_sub_paths, dst_path / src.name, missing_files_only) elif src.name.endswith('.la'): # Skip libtool files continue elif missing_files_only: for src_sub_path in src_sub_paths[1:]: - if not os.path.exists(src_sub_path): + if not src_sub_path.exists(): shutil.copy(src_sub_paths[0], dst_path) else: Builder._merge_file(src, src_sub_paths, dst_path) @@ -262,9 +259,9 @@ class Builder(object): cleanup = True - for dep in os.scandir(state.deps_path): + for dep in state.deps_path.iterdir(): if dep.is_dir(): - symlink_directory(dep.path, state.prefix_path, cleanup) + symlink_directory(dep, state.prefix_path, cleanup) # Do symlink cleanup only once cleanup = False diff --git a/aedi/state.py b/aedi/state.py index a058dac9..ef91d4fd 100644 --- a/aedi/state.py +++ b/aedi/state.py @@ -19,6 +19,7 @@ from distutils.version import StrictVersion import hashlib import os +from pathlib import Path import shutil import subprocess import urllib.request @@ -26,17 +27,17 @@ import urllib.request class BuildState: def __init__(self): - self_path = os.path.dirname(os.path.abspath(__file__)) - self.root_path = os.path.abspath(self_path + os.sep + os.pardir) + os.sep - self.deps_path = self.root_path + 'deps' + os.sep - self.prefix_path = self.root_path + 'prefix' + os.sep - self.bin_path = self.prefix_path + 'bin' + os.sep - self.include_path = self.prefix_path + 'include' + os.sep - self.lib_path = self.prefix_path + 'lib' + os.sep - self.patch_path = self.root_path + 'patch' + os.sep - self.source_path = self.root_path + 'source' + os.sep + self_path = Path(__file__) + self.root_path = self_path.parent.parent + self.deps_path = self.root_path / 'deps' + self.prefix_path = self.root_path / 'prefix' + self.bin_path = self.prefix_path / 'bin' + self.include_path = self.prefix_path / 'include' + self.lib_path = self.prefix_path / 'lib' + self.patch_path = self.root_path / 'patch' + self.source_path = self.root_path / 'source' - self.source = None + self.source = Path() self.external_source = True self.build_path = None @@ -69,7 +70,7 @@ class BuildState: return self.platform.cxx_compiler if self.platform else '' def checkout_git(self, url: str, branch: str = None): - if os.path.exists(self.source): + if self.source.exists(): return args = ('git', 'clone', '--recurse-submodules', url, self.source) @@ -102,13 +103,13 @@ class BuildState: # Adjust source and build paths according to extracted source code self.source = extract_path - self.build_path = self.build_path + first_path_component + os.sep + self.build_path = self.build_path / first_path_component - def _read_source_package(self, url: str) -> (bytes, str): + def _read_source_package(self, url: str) -> (bytes, Path): filename = url.rsplit(os.sep, 1)[1] - filepath = self.source + filename + filepath = self.source / filename - if os.path.exists(filepath): + if filepath.exists(): # Read existing source package with open(filepath, 'rb') as f: data = f.read() @@ -130,16 +131,16 @@ class BuildState: return data, filepath @staticmethod - def _verify_checksum(checksum: str, data: bytes, filepath: str) -> None: + def _verify_checksum(checksum: str, data: bytes, filepath: Path) -> None: file_hasher = hashlib.sha256() file_hasher.update(data) file_checksum = file_hasher.hexdigest() if file_checksum != checksum: - os.unlink(filepath) + filepath.unlink() raise Exception(f'Checksum of {filepath} does not match, expected: {checksum}, actual: {file_checksum}') - def _unpack_source_package(self, filepath: str) -> (str, str): + def _unpack_source_package(self, filepath: Path) -> (str, Path): filepaths = subprocess.check_output(['tar', '-tf', filepath]).decode("utf-8") filepaths = filepaths.split('\n') first_path_component = None @@ -150,11 +151,11 @@ class BuildState: break if not first_path_component: - raise Exception("Failed to figure out source code path for " + filepath) + raise Exception(f'Failed to figure out source code path for {filepath}') - extract_path = self.source + first_path_component + os.sep + extract_path = self.source / first_path_component - if not os.path.exists(extract_path): + if not extract_path.exists(): # Extract source code package try: subprocess.check_call(['tar', '-xf', filepath], cwd=self.source) @@ -164,14 +165,13 @@ class BuildState: return first_path_component, extract_path - def _apply_source_patch(self, extract_path: str, patch: str): - patch_path = self.patch_path + patch + '.diff' - - assert os.path.exists(patch_path) + def _apply_source_patch(self, extract_path: Path, patch: str): + patch_path = self.patch_path / (patch + '.diff') + assert patch_path.exists() # Check if patch is already applied test_arg = '--dry-run' - args = ['patch', test_arg, '--strip=1', '--input=' + patch_path] + args = ['patch', test_arg, '--strip=1', '--input=' + str(patch_path)] if subprocess.call(args, cwd=extract_path) == 0: # Patch wasn't applied yet, do it now @@ -181,7 +181,10 @@ class BuildState: def run_pkg_config(self, *args) -> str: os.makedirs(self.build_path, exist_ok=True) - args = (self.bin_path + 'pkg-config',) + args + args = (self.bin_path / 'pkg-config',) + args result = subprocess.check_output(args, cwd=self.build_path) return result.decode('utf-8').rstrip('\n') + + def has_source_file(self, path: [str, Path]): + return (self.source / path).exists() diff --git a/aedi/target/base.py b/aedi/target/base.py index 0822fa9e..c19e0222 100644 --- a/aedi/target/base.py +++ b/aedi/target/base.py @@ -19,6 +19,7 @@ import copy from distutils.version import StrictVersion import os +from pathlib import Path from platform import machine import re import shutil @@ -80,15 +81,18 @@ class BuildTarget(Target): sdk_path = state.sdk_path() if sdk_path: - match = re.search(r'/MacOSX(\d+.\d+).sdk', sdk_path, re.IGNORECASE) + match = re.search(r'/MacOSX(\d+.\d+).sdk', str(sdk_path), re.IGNORECASE) if match and StrictVersion(match[1]) < self.sdk_version[state.architecture()]: raise RuntimeError('Minimum SDK version requirement is not met') os.makedirs(state.build_path, exist_ok=True) env = self.environment - env['PATH'] = state.bin_path + os.pathsep + env['PATH'] \ - + os.pathsep + '/Applications/CMake.app/Contents/bin' + env['PATH'] = os.pathsep.join([ + str(state.bin_path), + env['PATH'], + '/Applications/CMake.app/Contents/bin' + ]) if state.xcode: return @@ -116,7 +120,7 @@ class BuildTarget(Target): def _set_sdk(self, state: BuildState, varname: str): sdk_path = state.sdk_path() if sdk_path: - self._update_env(varname, '-isysroot ' + sdk_path) + self._update_env(varname, f'-isysroot {sdk_path}') def _set_os_version(self, state: BuildState, varname: str): os_version = state.os_version() @@ -127,7 +131,7 @@ class BuildTarget(Target): if state.xcode: return - if os.path.exists(state.install_path): + if state.install_path.exists(): shutil.rmtree(state.install_path) args = [tool, 'install'] @@ -138,7 +142,7 @@ class BuildTarget(Target): self.update_pc_files(state) @staticmethod - def update_text_file(path: str, processor: typing.Callable = None): + def update_text_file(path: Path, processor: typing.Callable = None): with open(path, 'r') as f: content = f.readlines() @@ -154,7 +158,7 @@ class BuildTarget(Target): f.writelines(patched_content) @staticmethod - def _update_variables_file(path: str, prefix_value: str, processor: typing.Callable = None, quotes: bool = True): + def _update_variables_file(path: Path, prefix_value: str, processor: typing.Callable = None, quotes: bool = True): prefix = 'prefix=' exec_prefix = 'exec_prefix=' includedir = 'includedir=' @@ -183,11 +187,11 @@ class BuildTarget(Target): BuildTarget.update_text_file(path, patch_proc) @staticmethod - def update_config_script(path: str, processor: typing.Callable = None): + def update_config_script(path: Path, processor: typing.Callable = None): BuildTarget._update_variables_file(path, r'$(cd "${0%/*}/.."; pwd)', processor) @staticmethod - def update_pc_file(path: str, processor: typing.Callable = None): + def update_pc_file(path: Path, processor: typing.Callable = None): BuildTarget._update_variables_file(path, '', processor, quotes=False) def update_pc_files(self, state: BuildState): @@ -198,14 +202,14 @@ class BuildTarget(Target): BuildTarget.update_pc_file(file_path, self._process_pkg_config) @staticmethod - def _process_pkg_config(pcfile: str, line: str) -> str: + def _process_pkg_config(pcfile: Path, line: str) -> str: assert pcfile return line def write_pc_file(self, state: BuildState, filename=None, name=None, description=None, version='', requires='', requires_private='', libs='', libs_private='', cflags=''): - pkgconfig_path = state.install_path + '/lib/pkgconfig/' + pkgconfig_path = state.install_path / 'lib/pkgconfig' os.makedirs(pkgconfig_path, exist_ok=True) if not filename: @@ -231,19 +235,19 @@ Libs: -L${{libdir}} {libs} Libs.private: {libs_private} Cflags: -I${{includedir}} {cflags} ''' - with open(pkgconfig_path + filename, 'w') as f: + with open(pkgconfig_path / filename, 'w') as f: f.write(pc_content) @staticmethod def make_platform_header(state: BuildState, header: str): - include_path = state.install_path + os.sep + 'include' + os.sep + include_path = state.install_path / 'include' header_parts = header.rsplit(os.sep, 1) if len(header_parts) == 1: header_parts.insert(0, '') - common_header = include_path + header - platform_header = f'{include_path}{header_parts[0]}/_aedi_{state.architecture()}_{header_parts[1]}' + common_header = include_path / header + platform_header = include_path / header_parts[0] / f'_aedi_{state.architecture()}_{header_parts[1]}' shutil.move(common_header, platform_header) with open(common_header, 'w') as f: @@ -260,7 +264,7 @@ Cflags: -I${{includedir}} {cflags} ''') def copy_to_bin(self, state: BuildState, filename: str = None, new_filename: str = None): - bin_path = state.install_path + '/bin/' + bin_path = state.install_path / 'bin' os.makedirs(bin_path, exist_ok=True) if not filename: @@ -268,8 +272,8 @@ Cflags: -I${{includedir}} {cflags} if not new_filename: new_filename = filename - src_path = state.build_path + filename - dst_path = bin_path + new_filename + src_path = state.build_path / filename + dst_path = bin_path / new_filename shutil.copy(src_path, dst_path) @@ -289,12 +293,12 @@ class MakeTarget(BuildTarget): args = [ self.tool, '-j', state.jobs, - 'CC=' + state.c_compiler(), - 'CXX=' + state.cxx_compiler(), + f'CC={state.c_compiler()}', + f'CXX={state.cxx_compiler()}', ] args += self.options.to_list() - work_path = state.build_path + self.src_root + work_path = state.build_path / self.src_root subprocess.check_call(args, cwd=work_path, env=self.environment) @@ -307,12 +311,12 @@ class ConfigureMakeTarget(BuildTarget): super().configure(state) self.make.configure(state) - work_path = state.build_path + self.src_root - configure_path = work_path + os.sep + 'configure' + work_path = state.build_path / self.src_root + configure_path = work_path / 'configure' common_args = [ configure_path, - '--prefix=' + state.install_path, + f'--prefix={state.install_path}', ] common_args += self.options.to_list() @@ -347,10 +351,9 @@ class CMakeTarget(BuildTarget): super().__init__(name) def detect(self, state: BuildState) -> bool: - src_root = self.src_root and os.sep + self.src_root or '' - cmakelists_path = state.source + src_root + os.sep + 'CMakeLists.txt' + cmakelists_path = state.source / self.src_root / 'CMakeLists.txt' - if not os.path.exists(cmakelists_path): + if not cmakelists_path.exists(): return False for line in open(cmakelists_path).readlines(): @@ -386,16 +389,16 @@ class CMakeTarget(BuildTarget): args = [ 'cmake', '-DCMAKE_BUILD_TYPE=Release', - '-DCMAKE_INSTALL_PREFIX=' + state.install_path, - '-DCMAKE_PREFIX_PATH=' + state.prefix_path, + f'-DCMAKE_INSTALL_PREFIX={state.install_path}', + f'-DCMAKE_PREFIX_PATH={state.prefix_path}', ] if state.xcode: args.append('-GXcode') else: args.append('-GUnix Makefiles') - args.append('-DCMAKE_C_COMPILER=' + state.c_compiler()) - args.append('-DCMAKE_CXX_COMPILER=' + state.cxx_compiler()) + args.append(f'-DCMAKE_C_COMPILER={state.c_compiler()}') + args.append(f'-DCMAKE_CXX_COMPILER={state.cxx_compiler()}') architecture = state.architecture() if architecture != machine(): @@ -408,10 +411,10 @@ class CMakeTarget(BuildTarget): sdk_path = state.sdk_path() if sdk_path: - args.append('-DCMAKE_OSX_SYSROOT=' + sdk_path) + args.append(f'-DCMAKE_OSX_SYSROOT={sdk_path}') args += self.options.to_list(CommandLineOptions.CMAKE_RULES) - args.append(state.source + self.src_root) + args.append(state.source / self.src_root) subprocess.check_call(args, cwd=state.build_path, env=self.environment) @@ -477,7 +480,7 @@ class CMakeStaticDependencyTarget(CMakeTarget): module = 'targets-release.cmake' for probe_module in (module, self.name + module): - module_path = f'{state.install_path}/lib/cmake/{self.name}/{probe_module}' + module_path = state.install_path / 'lib' / 'cmake' / self.name / probe_module - if os.path.exists(module_path): + if module_path.exists(): self.update_text_file(module_path, _keep_target) diff --git a/aedi/target/library_tier1.py b/aedi/target/library_tier1.py index d73e4898..cbe47a1f 100644 --- a/aedi/target/library_tier1.py +++ b/aedi/target/library_tier1.py @@ -16,8 +16,6 @@ # along with this program. If not, see . # -import re - from .base import * from ..state import BuildState @@ -32,7 +30,7 @@ class Bzip2Target(MakeTarget): 'ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'bzlib.h') + return state.has_source_file('bzlib.h') def configure(self, state: BuildState): super().configure(state) @@ -62,7 +60,7 @@ class FfiTarget(ConfigureMakeStaticDependencyTarget): '540fb721619a6aba3bdeef7d940d8e9e0e6d2c193595bc243241b77ff9e93620') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'libffi.pc.in') + return state.has_source_file('libffi.pc.in') def post_build(self, state: BuildState): super().post_build(state) @@ -88,17 +86,17 @@ class FlacTarget(CMakeStaticDependencyTarget): patches='flac-add-cmake') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'FLAC/flac.pc.in') + return state.has_source_file('FLAC/flac.pc.in') def configure(self, state: BuildState): - self.options['CMAKE_EXE_LINKER_FLAGS'] = '-framework CoreFoundation -L' + state.lib_path + self.options['CMAKE_EXE_LINKER_FLAGS'] = f'-framework CoreFoundation -L{state.lib_path}' super().configure(state) def post_build(self, state: BuildState): super().post_build(state) - shutil.copytree(state.install_path + 'share/FLAC/cmake', state.install_path + 'lib/cmake/FLAC') - shutil.copytree(state.install_path + 'share/pkgconfig', state.install_path + 'lib/pkgconfig') + shutil.copytree(state.install_path / 'share/FLAC/cmake', state.install_path / 'lib/cmake/FLAC') + shutil.copytree(state.install_path / 'share/pkgconfig', state.install_path / 'lib/pkgconfig') self.keep_module_target(state, 'FLAC::FLAC') @@ -119,7 +117,7 @@ class FluidSynthTarget(CMakeStaticDependencyTarget): '695aedbfd53160fef7a9a1f66cd6d5cc8a5da0fd472eee458d82b848b6065f9a') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'fluidsynth.pc.in') + return state.has_source_file('fluidsynth.pc.in') def configure(self, state: BuildState): # TODO: Figure out why private dependencies aren't pulled @@ -142,7 +140,7 @@ class GettextTarget(ConfigureMakeStaticDependencyTarget): 'd20fcbb537e02dcf1383197ba05bd0734ef7bf5db06bdb241eb69b7d16b73192') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'gettext-runtime') + return state.has_source_file('gettext-runtime') class GlibTarget(BuildTarget): @@ -155,7 +153,7 @@ class GlibTarget(BuildTarget): 'e7e1a3c20c026109c45c9ec4a31d8dcebc22e86c69486993e565817d64be3138') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'glib.doap') + return state.has_source_file('glib.doap') def configure(self, state: BuildState): super().configure(state) @@ -166,7 +164,7 @@ class GlibTarget(BuildTarget): cpu = state.architecture() cpu_family = 'arm' if 'arm64' == cpu else cpu - cross_file = state.build_path + state.architecture() + '.txt' + cross_file = state.build_path / (state.architecture() + '.txt') with open(cross_file, 'w') as f: f.write(f''' [binaries] @@ -185,11 +183,11 @@ endian = 'little' ''') args = ( - state.bin_path + 'meson', - '--prefix=' + state.install_path, + state.bin_path / 'meson', + f'--prefix={state.install_path}', '--buildtype=release', '--default-library=static', - '--cross-file=' + cross_file, + f'--cross-file={cross_file}', state.source ) subprocess.check_call(args, cwd=state.build_path, env=environment) @@ -218,7 +216,7 @@ class IconvTarget(ConfigureMakeStaticDependencyTarget): 'e6a1b1b589654277ee790cce3734f07876ac4ccfaecbee8afa0b649cf529cc04') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'include/iconv.h.in') + return state.has_source_file('include/iconv.h.in') class InstPatchTarget(CMakeStaticDependencyTarget): @@ -235,7 +233,7 @@ class InstPatchTarget(CMakeStaticDependencyTarget): '8e9861b04ede275d712242664dab6ffa9166c7940fea3b017638681d25e10299') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'libinstpatch-1.0.pc.in') + return state.has_source_file('libinstpatch-1.0.pc.in') class IntlTarget(GettextTarget): @@ -261,7 +259,7 @@ class JpegTurboTarget(CMakeStaticDependencyTarget): 'bef89803e506f27715c5627b1e3219c95b80fc31465d4452de2a909d382e4444') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'turbojpeg.h') + return state.has_source_file('turbojpeg.h') class MoltenVKTarget(MakeTarget): @@ -277,7 +275,7 @@ class MoltenVKTarget(MakeTarget): 'f9bba6d3bf3648e7685c247cb6d126d62508af614bc549cedd5859a7da64967e') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'MoltenVKPackaging.xcodeproj') + return state.has_source_file('MoltenVKPackaging.xcodeproj') def configure(self, state: BuildState): # Unset platform to avoid using specified macOS deployment target and SDK @@ -296,16 +294,16 @@ class MoltenVKTarget(MakeTarget): if state.xcode: return - if os.path.exists(state.install_path): + if state.install_path.exists(): shutil.rmtree(state.install_path) - lib_path = state.install_path + os.sep + 'lib' + os.sep + lib_path = state.install_path / 'lib' os.makedirs(lib_path) - src_path = state.build_path + 'Package/Latest/MoltenVK/' - shutil.copytree(src_path + 'include', state.install_path + os.sep + 'include') - shutil.copy(state.build_path + 'LICENSE', state.install_path + os.sep + 'apache2.txt') - shutil.copy(src_path + 'dylib/macOS/libMoltenVK.dylib', lib_path) + src_path = state.build_path / 'Package/Latest/MoltenVK' + shutil.copytree(src_path / 'include', state.install_path / 'include') + shutil.copy(state.build_path + 'LICENSE', state.install_path / 'apache2.txt') + shutil.copy(src_path / 'dylib/macOS/libMoltenVK.dylib', lib_path) class Mpg123Target(CMakeStaticDependencyTarget): @@ -322,7 +320,7 @@ class Mpg123Target(CMakeStaticDependencyTarget): patches='mpg123-fix-cmake') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'libmpg123.pc.in') + return state.has_source_file('libmpg123.pc.in') def post_build(self, state: BuildState): super().post_build(state) @@ -339,7 +337,7 @@ class OggTarget(CMakeStaticDependencyTarget): 'c4d91be36fc8e54deae7575241e03f4211eb102afb3fc0775fbbc1b740016705') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'ogg.pc.in') + return state.has_source_file('ogg.pc.in') class OpenALTarget(CMakeStaticDependencyTarget): @@ -356,7 +354,7 @@ class OpenALTarget(CMakeStaticDependencyTarget): 'c8ad767e9a3230df66756a21cc8ebf218a9d47288f2514014832204e666af5d8') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'openal.pc.in') + return state.has_source_file('openal.pc.in') FRAMEWORKS = '-framework ApplicationServices -framework AudioToolbox -framework AudioUnit -framework CoreAudio' @@ -367,7 +365,7 @@ class OpenALTarget(CMakeStaticDependencyTarget): link_libs = ' INTERFACE_LINK_LIBRARIES ' return f'{link_libs}"{OpenALTarget.FRAMEWORKS}"\n' if line.startswith(link_libs) else line - config_path = state.install_path + '/lib/cmake/OpenAL/OpenALConfig.cmake' + config_path = state.install_path / 'lib/cmake/OpenAL/OpenALConfig.cmake' self.update_text_file(config_path, update_cmake_libs) @staticmethod @@ -388,7 +386,7 @@ class OpusTarget(CMakeStaticDependencyTarget): patches='opus-fix-cmake') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'opus.pc.in') + return state.has_source_file('opus.pc.in') @staticmethod def _process_pkg_config(pcfile: str, line: str) -> str: @@ -420,11 +418,11 @@ class PcreTarget(ConfigureMakeStaticDependencyTarget): '4dae6fdcd2bb0bb6c37b5f97c33c2be954da743985369cddac3546e3218bffb8') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'pcre.h.in') + return state.has_source_file('pcre.h.in') def post_build(self, state: BuildState): super().post_build(state) - self.update_config_script(state.install_path + '/bin/pcre-config') + self.update_config_script(state.install_path / 'bin/pcre-config') class SndFileTarget(CMakeStaticDependencyTarget): @@ -441,7 +439,7 @@ class SndFileTarget(CMakeStaticDependencyTarget): 'a8cfb1c09ea6e90eff4ca87322d4168cdbe5035cb48717b40bf77e751cc02163') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'sndfile.pc.in') + return state.has_source_file('sndfile.pc.in') class VorbisTarget(CMakeStaticDependencyTarget): @@ -454,7 +452,7 @@ class VorbisTarget(CMakeStaticDependencyTarget): 'b33cc4934322bcbf6efcbacf49e3ca01aadbea4114ec9589d1b1e9d20f72954b') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'vorbis.pc.in') + return state.has_source_file('vorbis.pc.in') class VpxTarget(ConfigureMakeDependencyTarget): @@ -480,7 +478,7 @@ class VpxTarget(ConfigureMakeDependencyTarget): super().configure(state) def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'vpxstats.h') + return state.has_source_file('vpxstats.h') class ZlibNgTarget(CMakeStaticDependencyTarget): @@ -498,7 +496,7 @@ class ZlibNgTarget(CMakeStaticDependencyTarget): 'eca3fe72aea7036c31d00ca120493923c4d5b99fe02e6d3322f7c88dbdcd0085') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'zlib-ng.h') + return state.has_source_file('zlib-ng.h') class ZMusicTarget(CMakeStaticDependencyTarget): @@ -516,4 +514,4 @@ class ZMusicTarget(CMakeStaticDependencyTarget): '73082f661b7b0bb33348d1d186c132deec9132a1613480348a00172b49c9fd68') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'include/zmusic.h') + return state.has_source_file('include/zmusic.h') diff --git a/aedi/target/library_tier2.py b/aedi/target/library_tier2.py index a95fd560..71cb5900 100644 --- a/aedi/target/library_tier2.py +++ b/aedi/target/library_tier2.py @@ -34,7 +34,7 @@ class DumbTarget(CMakeStaticDependencyTarget): '99bfac926aeb8d476562303312d9f47fd05b43803050cd889b44da34a9b2a4f9') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'include/dumb.h') + return state.has_source_file('include/dumb.h') @staticmethod def _process_pkg_config(pcfile: str, line: str) -> str: @@ -56,7 +56,7 @@ class ExpatTarget(CMakeStaticDependencyTarget): 'cf032d0dba9b928636548e32b327a2d66b1aab63c4f4a13dd132c2d1d2f2fb6a') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'expat.pc.in') + return state.has_source_file('expat.pc.in') class FmtTarget(CMakeStaticDependencyTarget): @@ -73,7 +73,7 @@ class FmtTarget(CMakeStaticDependencyTarget): '5cae7072042b3043e12d53d50ef404bbb76949dad1de368d7f993a15c8c05ecc') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'include/fmt/format.h') + return state.has_source_file('include/fmt/format.h') class FreeImageTarget(MakeTarget): @@ -89,7 +89,7 @@ class FreeImageTarget(MakeTarget): HEADER_FILE = 'Source/FreeImage.h' def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + self.HEADER_FILE) + return state.has_source_file(self.HEADER_FILE) def configure(self, state: BuildState): super().configure(state) @@ -105,13 +105,13 @@ class FreeImageTarget(MakeTarget): self.options[option] = None def post_build(self, state: BuildState): - include_path = state.install_path + 'include' + include_path = state.install_path / 'include' os.makedirs(include_path, exist_ok=True) - shutil.copy(state.build_path + self.HEADER_FILE, include_path) + shutil.copy(state.build_path / self.HEADER_FILE, include_path) - lib_path = state.install_path + 'lib' + lib_path = state.install_path / 'lib' os.makedirs(lib_path, exist_ok=True) - shutil.copy(state.build_path + 'libfreeimage.a', lib_path) + shutil.copy(state.build_path / 'libfreeimage.a', lib_path) self.write_pc_file(state, version='3.18.0', libs='-lfreeimage -lc++') @@ -126,14 +126,14 @@ class FreeTypeTarget(CMakeStaticDependencyTarget): '86a854d8905b19698bbc8f23b860bc104246ce4854dcea8e3b0fb21284f75784') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'include/freetype/freetype.h') + return state.has_source_file('include/freetype/freetype.h') def post_build(self, state: BuildState): super().post_build(state) - bin_path = state.install_path + 'bin' + bin_path = state.install_path / 'bin' os.makedirs(bin_path) - shutil.copy(state.patch_path + 'freetype-config', bin_path) + shutil.copy(state.patch_path / 'freetype-config', bin_path) class FtglTarget(ConfigureMakeStaticDependencyTarget): @@ -151,7 +151,7 @@ class FtglTarget(ConfigureMakeStaticDependencyTarget): patches='ftgl-support-arm64') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'ftgl.pc.in') + return state.has_source_file('ftgl.pc.in') class GlewTarget(CMakeStaticDependencyTarget): @@ -167,7 +167,7 @@ class GlewTarget(CMakeStaticDependencyTarget): 'd4fc82893cfb00109578d0a1a2337fb8ca335b3ceccf97b97e5cc7f08e4353e1') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'glew.pc.in') + return state.has_source_file('glew.pc.in') LINKER_FLAGS = '-framework OpenGL' @@ -182,7 +182,7 @@ class GlewTarget(CMakeStaticDependencyTarget): return line - cmake_module = state.install_path + 'lib/cmake/glew/glew-targets.cmake' + cmake_module = state.install_path / 'lib/cmake/glew/glew-targets.cmake' self.update_text_file(cmake_module, update_linker_flags) @staticmethod @@ -205,7 +205,7 @@ class LuaTarget(MakeTarget): 'f8612276169e3bfcbcfb8f226195bfc6e466fe13042f1076cbde92b7ec96bbfb') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'src/lua.h') + return state.has_source_file('src/lua.h') def post_build(self, state: BuildState): self.options['INSTALL_TOP'] = state.install_path @@ -223,7 +223,7 @@ class LzmaTarget(CMakeStaticDependencyTarget): patches='lzma-add-cmake') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'src/liblzma/liblzma.pc.in') + return state.has_source_file('src/liblzma/liblzma.pc.in') def post_build(self, state: BuildState): super().post_build(state) @@ -245,7 +245,7 @@ class MadTarget(ConfigureMakeStaticDependencyTarget): patches='mad-support-arm64') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'mad.h') + return state.has_source_file('mad.h') def post_build(self, state: BuildState): super().post_build(state) @@ -262,11 +262,11 @@ class MikmodTarget(ConfigureMakeStaticDependencyTarget): 'ad9d64dfc8f83684876419ea7cd4ff4a41d8bcd8c23ef37ecb3a200a16b46d19') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'libmikmod.pc.in') + return state.has_source_file('libmikmod.pc.in') def post_build(self, state: BuildState): super().post_build(state) - self.update_config_script(state.install_path + '/bin/libmikmod-config') + self.update_config_script(state.install_path / 'bin/libmikmod-config') class ModPlugTarget(ConfigureMakeStaticDependencyTarget): @@ -279,7 +279,7 @@ class ModPlugTarget(ConfigureMakeStaticDependencyTarget): '457ca5a6c179656d66c01505c0d95fafaead4329b9dbaa0f997d00a3508ad9de') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'libmodplug.pc.in') + return state.has_source_file('libmodplug.pc.in') @staticmethod def _process_pkg_config(pcfile: str, line: str) -> str: @@ -302,7 +302,7 @@ class OpusFileTarget(ConfigureMakeStaticDependencyTarget): '118d8601c12dd6a44f52423e68ca9083cc9f2bfe72da7a8c1acb22a80ae3550b') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'opusfile.pc.in') + return state.has_source_file('opusfile.pc.in') class PngTarget(CMakeStaticDependencyTarget): @@ -319,11 +319,11 @@ class PngTarget(CMakeStaticDependencyTarget): '505e70834d35383537b6491e7ae8641f1a4bed1876dbfe361201fc80868d88ca') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'libpng.pc.in') + return state.has_source_file('libpng.pc.in') def post_build(self, state: BuildState): super().post_build(state) - self.update_config_script(state.install_path + '/bin/libpng16-config') + self.update_config_script(state.install_path / 'bin/libpng16-config') class PortMidiTarget(CMakeTarget): @@ -337,20 +337,20 @@ class PortMidiTarget(CMakeTarget): patches='portmidi-modernize-cmake') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'pm_common/portmidi.h') + return state.has_source_file('pm_common/portmidi.h') def post_build(self, state: BuildState): - if os.path.exists(state.install_path): + if state.install_path.exists(): shutil.rmtree(state.install_path) - include_path = state.install_path + os.sep + 'include' + include_path = state.install_path / 'include' os.makedirs(include_path) - shutil.copy(state.source + 'pm_common/portmidi.h', include_path) - shutil.copy(state.source + 'porttime/porttime.h', include_path) + shutil.copy(state.source / 'pm_common/portmidi.h', include_path) + shutil.copy(state.source / 'porttime/porttime.h', include_path) - lib_path = state.install_path + os.sep + 'lib' + os.sep + lib_path = state.install_path / 'lib' os.makedirs(lib_path) - shutil.copy(state.build_path + 'libportmidi_s.a', lib_path + 'libportmidi.a') + shutil.copy(state.build_path / 'libportmidi_s.a', lib_path / 'libportmidi.a') class SamplerateTarget(CMakeStaticDependencyTarget): @@ -364,7 +364,7 @@ class SamplerateTarget(CMakeStaticDependencyTarget): patches='samplerate-support-arm64') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'samplerate.pc.in') + return state.has_source_file('samplerate.pc.in') class Sdl2Target(CMakeStaticDependencyTarget): @@ -384,7 +384,7 @@ class Sdl2Target(CMakeStaticDependencyTarget): 'd8215b571a581be1332d2106f8036fcb03d12a70bae01e20f424976d275432bc') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'sdl2.pc.in') + return state.has_source_file('sdl2.pc.in') FRAMEWORKS = '-framework AudioToolbox -framework AVFoundation -framework Carbon -framework Cocoa' \ ' -framework CoreAudio -framework CoreFoundation -framework CoreVideo' \ @@ -402,7 +402,7 @@ class Sdl2Target(CMakeStaticDependencyTarget): return line - self.update_config_script(state.install_path + '/bin/sdl2-config', update_sdl2_config) + self.update_config_script(state.install_path / 'bin/sdl2-config', update_sdl2_config) def update_targets_cmake(line: str): if line.startswith(' INTERFACE_LINK_LIBRARIES '): @@ -413,7 +413,7 @@ class Sdl2Target(CMakeStaticDependencyTarget): return line for suffix in ('', '-release'): - file_path = f'{state.install_path}/lib/cmake/SDL2/SDL2Targets{suffix}.cmake' + file_path = state.install_path / f'lib/cmake/SDL2/SDL2Targets{suffix}.cmake' self.update_text_file(file_path, update_targets_cmake) @staticmethod @@ -436,7 +436,7 @@ class Sdl2ImageTarget(ConfigureMakeStaticDependencyTarget): 'bdd5f6e026682f7d7e1be0b6051b209da2f402a2dd8bd1c4bd9c25ad263108d0') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'SDL2_image.pc.in') + return state.has_source_file('SDL2_image.pc.in') @staticmethod def _process_pkg_config(pcfile: str, line: str) -> str: @@ -461,7 +461,7 @@ class Sdl2MixerTarget(ConfigureMakeStaticDependencyTarget): super().configure(state) def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'SDL2_mixer.pc.in') + return state.has_source_file('SDL2_mixer.pc.in') @staticmethod def _process_pkg_config(pcfile: str, line: str) -> str: @@ -481,7 +481,7 @@ class Sdl2NetTarget(ConfigureMakeStaticDependencyTarget): '15ce8a7e5a23dafe8177c8df6e6c79b6749a03fff1e8196742d3571657609d21') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'SDL2_net.pc.in') + return state.has_source_file('SDL2_net.pc.in') class Sdl2TtfTarget(CMakeStaticDependencyTarget): @@ -496,11 +496,11 @@ class Sdl2TtfTarget(CMakeStaticDependencyTarget): patches='sdl2_ttf-fix-cmake') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'SDL2_ttf.pc.in') + return state.has_source_file('SDL2_ttf.pc.in') def post_build(self, state: BuildState): super().post_build(state) - shutil.move(state.install_path + 'SDL2_ttf.framework/Resources', state.install_path + 'lib/cmake/SDL2_ttf') + shutil.move(state.install_path / 'SDL2_ttf.framework/Resources', state.install_path / 'lib/cmake/SDL2_ttf') @staticmethod def _process_pkg_config(pcfile: str, line: str) -> str: @@ -517,7 +517,7 @@ class SodiumTarget(ConfigureMakeStaticDependencyTarget): '6f504490b342a4f8a4c4a02fc9b866cbef8622d5df4e5452b46be121e46636c1') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'libsodium.pc.in') + return state.has_source_file('libsodium.pc.in') class SfmlTarget(CMakeStaticDependencyTarget): @@ -534,15 +534,15 @@ class SfmlTarget(CMakeStaticDependencyTarget): opts = self.options opts['CMAKE_OSX_ARCHITECTURES'] = state.architecture() opts['SFML_USE_SYSTEM_DEPS'] = 'YES' - opts['SFML_MISC_INSTALL_PREFIX'] = state.install_path + 'share/SFML' + opts['SFML_MISC_INSTALL_PREFIX'] = state.install_path / 'share/SFML' # Use OpenAL Soft instead of Apple's framework - opts['OPENAL_INCLUDE_DIR'] = state.include_path + 'AL' - opts['OPENAL_LIBRARY'] = state.lib_path + 'libopenal.a' + opts['OPENAL_INCLUDE_DIR'] = state.include_path / 'AL' + opts['OPENAL_LIBRARY'] = state.lib_path / 'libopenal.a' super(SfmlTarget, self).configure(state) def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'libtiff-4.pc.in') + return state.has_source_file('libtiff-4.pc.in') class TiffTarget(CMakeStaticDependencyTarget): @@ -560,7 +560,7 @@ class TiffTarget(CMakeStaticDependencyTarget): patches='tiff-remove-useless') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'libtiff-4.pc.in') + return state.has_source_file('libtiff-4.pc.in') @staticmethod def _process_pkg_config(pcfile: str, line: str) -> str: @@ -599,12 +599,12 @@ class WebpTarget(CMakeStaticDependencyTarget): '2fc8bbde9f97f2ab403c0224fb9ca62b2e6852cbc519e91ceaa7c153ffd88a0c') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'src/libwebp.pc.in') + return state.has_source_file('src/libwebp.pc.in') def post_build(self, state: BuildState): super().post_build(state) - shutil.copytree(state.install_path + 'share/WebP/cmake', state.install_path + 'lib/cmake/WebP') + shutil.copytree(state.install_path / 'share/WebP/cmake', state.install_path / 'lib/cmake/WebP') self.keep_module_target(state, 'WebP::webp') @@ -630,7 +630,7 @@ class WxWidgetsTarget(CMakeStaticDependencyTarget): patches='wxwidgets-library-suffix') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'wx-config.in') + return state.has_source_file('wx-config.in') def post_build(self, state: BuildState): super().post_build(state) @@ -640,7 +640,7 @@ class WxWidgetsTarget(CMakeStaticDependencyTarget): prefix = '#define wxINSTALL_PREFIX ' return f'{prefix}"/usr/local"\n' if line.startswith(prefix) else line - setup_h_path = state.install_path + 'lib/wx/include/osx_cocoa-unicode-static-3.1/wx/setup.h' + setup_h_path = state.install_path / 'lib/wx/include/osx_cocoa-unicode-static-3.1/wx/setup.h' self.update_text_file(setup_h_path, patch_setup_h) # Fix a few wx-config entries @@ -670,7 +670,7 @@ class WxWidgetsTarget(CMakeStaticDependencyTarget): return line - wx_config_path = state.install_path + 'bin/wx-config' + wx_config_path = state.install_path / 'bin/wx-config' self.update_text_file(wx_config_path, patch_wx_config) @@ -689,4 +689,4 @@ class ZstdTarget(CMakeStaticDependencyTarget): '5194fbfa781fcf45b98c5e849651aa7b3b0a008c6b72d4a0db760f3002291e94') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'lib/libzstd.pc.in') + return state.has_source_file('lib/libzstd.pc.in') diff --git a/aedi/target/main.py b/aedi/target/main.py index 97c9ee2a..f9abfb69 100644 --- a/aedi/target/main.py +++ b/aedi/target/main.py @@ -43,17 +43,17 @@ class CMakeMainTarget(CMakeTarget): if state.xcode: return - if os.path.exists(state.install_path): + if state.install_path.exists(): shutil.rmtree(state.install_path) os.makedirs(state.install_path) for output in self.outputs: - src = state.build_path + output + src = state.build_path / output dst_sep_pos = output.rfind(os.sep) - dst = state.install_path + os.sep + (output if dst_sep_pos == -1 else output[dst_sep_pos + 1:]) + dst = state.install_path / (output if dst_sep_pos == -1 else output[dst_sep_pos + 1:]) - copy_func = shutil.copytree if os.path.isdir(src) else shutil.copy + copy_func = shutil.copytree if src.is_dir() else shutil.copy copy_func(src, dst) def _force_cross_compilation(self, state: BuildState): @@ -62,7 +62,7 @@ class CMakeMainTarget(CMakeTarget): opts = self.options opts['FORCE_CROSSCOMPILE'] = 'YES' - opts['IMPORT_EXECUTABLES'] = state.native_build_path + 'ImportExecutables.cmake' + opts['IMPORT_EXECUTABLES'] = state.native_build_path / 'ImportExecutables.cmake' class ZDoomBaseTarget(CMakeMainTarget): @@ -75,8 +75,8 @@ class ZDoomBaseTarget(CMakeMainTarget): opts['PK3_QUIET_ZIPDIR'] = 'YES' opts['DYN_OPENAL'] = 'NO' # Explicit OpenAL configuration to avoid selection of Apple's framework - opts['OPENAL_INCLUDE_DIR'] = state.include_path + 'AL' - opts['OPENAL_LIBRARY'] = state.lib_path + 'libopenal.a' + opts['OPENAL_INCLUDE_DIR'] = state.include_path / 'AL' + opts['OPENAL_LIBRARY'] = state.lib_path / 'libopenal.a' self._force_cross_compilation(state) @@ -90,19 +90,19 @@ class ZDoomVulkanBaseTarget(ZDoomBaseTarget): def post_build(self, state: BuildState): # Put MoltenVK library into application bundle molten_lib = 'libMoltenVK.dylib' - src_path = state.lib_path + molten_lib + src_path = state.lib_path / molten_lib dst_path = state.build_path if state.xcode: # TODO: Support other configurations - dst_path += 'Debug' + os.sep + dst_path /= 'Debug' - dst_path += self.name + '.app/Contents/MacOS' + os.sep + dst_path /= self.name + '.app/Contents/MacOS' os.makedirs(dst_path, exist_ok=True) - dst_path += molten_lib + dst_path /= molten_lib - if not os.path.exists(dst_path): + if not dst_path.exists(): copy_func = state.xcode and os.symlink or shutil.copy copy_func(src_path, dst_path) @@ -133,7 +133,7 @@ class LZDoomTarget(ZDoomVulkanBaseTarget): state.checkout_git('https://github.com/drfrag666/gzdoom.git') def detect(self, state: BuildState) -> bool: - return super().detect(state) and not os.path.exists(state.source + 'libraries/zmusic') + return super().detect(state) and not state.has_source_file('libraries/zmusic') class LZDoom3Target(ZDoomBaseTarget): @@ -150,7 +150,7 @@ class LZDoom3Target(ZDoomBaseTarget): state.checkout_git('https://github.com/drfrag666/gzdoom.git', branch='g3.3mgw') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'ico_lzdoom.png') and os.path.exists(state.source + 'libraries/zmusic') + return state.has_source_file('ico_lzdoom.png') and state.has_source_file('libraries/zmusic') class RazeTarget(ZDoomVulkanBaseTarget): @@ -183,7 +183,7 @@ class SladeTarget(CMakeMainTarget): state.checkout_git('https://github.com/sirjuddington/SLADE.git', branch='stable') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'SLADE-osx.icns') + return state.has_source_file('SLADE-osx.icns') def configure(self, state: BuildState): opts = self.options @@ -323,10 +323,8 @@ class DevilutionXTarget(CMakeMainTarget): super().configure(state) # Remove version file that is included erroneously because of case-insensitive file system - version_file = state.build_path + '_deps/libzt-src/ext/ZeroTierOne/ext/miniupnpc/VERSION' - - if os.path.exists(version_file): - os.unlink(version_file) + version_file = state.build_path / '_deps/libzt-src/ext/ZeroTierOne/ext/miniupnpc/VERSION' + version_file.unlink(missing_ok=True) class EDuke32Target(MakeMainTarget): @@ -338,8 +336,8 @@ class EDuke32Target(MakeMainTarget): def detect(self, state: BuildState) -> bool: def has_bundle(name: str) -> bool: - probe_path = f'{state.source}/platform/Apple/bundles/{name}.app' - return os.path.exists(probe_path) + probe_path = state.source / 'platform/Apple/bundles/{name}.app' + return probe_path.exists() return has_bundle('EDuke32') and not has_bundle('NBlood') @@ -362,7 +360,7 @@ class NBloodTarget(EDuke32Target): state.checkout_git('https://github.com/nukeykt/NBlood.git') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + os.sep + 'nblood.pk3') + return state.has_source_file('nblood.pk3') class QuakespasmTarget(MakeMainTarget): @@ -385,4 +383,4 @@ class QuakespasmTarget(MakeMainTarget): state.checkout_git('https://git.code.sf.net/p/quakespasm/quakespasm') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + os.sep + 'Quakespasm.txt') + return state.has_source_file('Quakespasm.txt') diff --git a/aedi/target/special.py b/aedi/target/special.py index 01d7eb1f..c07841a6 100644 --- a/aedi/target/special.py +++ b/aedi/target/special.py @@ -16,7 +16,7 @@ # along with this program. If not, see . # -import os +from pathlib import Path import shlex import shutil import subprocess @@ -60,14 +60,14 @@ class DownloadCMakeTarget(Target): def build(self, state: BuildState): probe_paths = ( - '', + Path(), state.bin_path, - '/Applications/CMake.app/Contents/bin/', + Path('/Applications/CMake.app/Contents/bin/'), ) for path in probe_paths: try: - subprocess.run([path + 'cmake', '--version'], check=True) + subprocess.run([path / 'cmake', '--version'], check=True) return except (FileNotFoundError, IOError, subprocess.CalledProcessError): continue @@ -79,14 +79,14 @@ class DownloadCMakeTarget(Target): f'https://github.com/Kitware/CMake/releases/download/v{cmake_version}/{cmake_basename}.tar.gz', '000828af55268853ba21b91f8ce3bfb9365aa72aee960fc7f0c01a71f3a2217a') - target_path = state.deps_path + 'cmake' - if os.path.exists(target_path): + target_path = state.deps_path / 'cmake' + if target_path.exists(): shutil.rmtree(target_path) - os.makedirs(target_path) + target_path.mkdir() - source_path = state.source + 'CMake.app/Contents/' - shutil.move(source_path + 'bin', target_path) - shutil.move(source_path + 'share', target_path) + source_path = state.source / 'CMake.app' / 'Contents' + shutil.move(str(source_path / 'bin'), target_path) + shutil.move(str(source_path / 'share'), target_path) shutil.rmtree(state.source) @@ -98,15 +98,15 @@ class TestDepsTarget(BuildTarget): def build(self, state: BuildState): assert not state.xcode - test_path = state.root_path + 'test' + test_path = state.root_path / 'test' - for entry in os.scandir(test_path): + for entry in test_path.iterdir(): if not entry.name.endswith('.cpp'): continue - test_name = os.path.splitext(entry.name)[0] + test_name = entry.stem pkg_config_output = state.run_pkg_config('--cflags', '--libs', test_name) - exe_name = state.build_path + test_name + exe_name = state.build_path / test_name print('Testing ' + test_name) @@ -115,9 +115,9 @@ class TestDepsTarget(BuildTarget): '-arch', 'x86_64', '-arch', 'arm64', '-std=c++17', - '-include', os.path.join(test_path, 'aedi.h'), + '-include', test_path / 'aedi.h', '-o', exe_name, - entry.path, + entry, ] args += shlex.split(pkg_config_output) subprocess.run(args, cwd=state.build_path, check=True) diff --git a/aedi/target/tools.py b/aedi/target/tools.py index fc941238..a94ed092 100644 --- a/aedi/target/tools.py +++ b/aedi/target/tools.py @@ -34,7 +34,7 @@ class GmakeTarget(ConfigureMakeDependencyTarget): 'de1a441c4edf952521db30bfca80baae86a0ff1acd0a00402999344f04c45e82') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'doc/make.1') + return state.has_source_file('doc/make.1') def post_build(self, state: BuildState): self.copy_to_bin(state, 'make', self.name) @@ -51,16 +51,16 @@ class MesonTarget(BuildTarget): '3144a3da662fcf79f1e5602fa929f2821cba4eba28c2c923fe0a7d3e3db04d5d') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'meson.py') + return state.has_source_file('meson.py') def post_build(self, state: BuildState): - dest_path = os.path.join(state.install_path, 'bin') + dest_path = state.install_path / 'bin' os.makedirs(dest_path) def directory_filter(path: pathlib.Path) -> bool: return path.parts[0].startswith('mesonbuild') - zipapp.create_archive(source=state.source, target=os.path.join(dest_path, self.name), + zipapp.create_archive(source=state.source, target=dest_path / self.name, interpreter='/usr/bin/env python3', main='mesonbuild.mesonmain:main', filter=directory_filter, compressed=True) @@ -75,7 +75,7 @@ class NasmTarget(ConfigureMakeDependencyTarget): '3caf6729c1073bf96629b57cee31eeb54f4f8129b01902c73428836550b30a3f') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'nasm.txt') + return state.has_source_file('nasm.txt') class NinjaTarget(MakeTarget): @@ -88,7 +88,7 @@ class NinjaTarget(MakeTarget): 'ce35865411f0490368a8fc383f29071de6690cbadc27704734978221f25e2bed') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'src/ninja.cc') + return state.has_source_file('src/ninja.cc') def build(self, state: BuildState): cmdlines = ( @@ -114,8 +114,8 @@ class P7ZipTarget(CMakeTarget): 'ea029a2e21d2d6ad0a156f6679bd66836204aa78148a4c5e498fe682e77127ef') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'CPP/7zip/CMAKE/CMakeLists.txt') \ - and os.path.exists(state.source + 'C/fast-lzma2/fast-lzma2.h') + return state.has_source_file('CPP/7zip/CMAKE/CMakeLists.txt') \ + and state.has_source_file('C/fast-lzma2/fast-lzma2.h') def post_build(self, state: BuildState): self.copy_to_bin(state, '7za') @@ -131,7 +131,7 @@ class PkgConfigTarget(ConfigureMakeDependencyTarget): '6fc69c01688c9458a57eb9a1664c9aba372ccda420a02bf4429fe610e7e7d591') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'pkg-config.1') + return state.has_source_file('pkg-config.1') def post_build(self, state: BuildState): self.copy_to_bin(state, new_filename=self.name + '.exe') @@ -147,7 +147,7 @@ class YasmTarget(ConfigureMakeDependencyTarget): '3dce6601b495f5b3d45b59f7d2492a340ee7e84b5beca17e48f862502bd5603f') def detect(self, state: BuildState) -> bool: - return os.path.exists(state.source + 'libyasm.h') + return state.has_source_file('libyasm.h') class UnrarTarget(MakeTarget): diff --git a/aedi/utility.py b/aedi/utility.py index 53fbfa7f..df9c3d52 100644 --- a/aedi/utility.py +++ b/aedi/utility.py @@ -16,9 +16,10 @@ # along with this program. If not, see . # -import collections +import collections.abc from distutils.version import StrictVersion import os +from pathlib import Path import shutil @@ -51,39 +52,36 @@ class CommandLineOptions(dict): class TargetPlatform: def __init__(self, architecture: str, host: str, os_version: [str, StrictVersion], - sdk_path: str, prefix_path: str): + sdk_path: Path, prefix_path: Path): self.architecture = architecture self.host = host self.os_version = os_version if isinstance(os_version, StrictVersion) else StrictVersion(os_version) self.sdk_path = sdk_path - self.c_compiler = f'{prefix_path}bin/{host}-gcc' - self.cxx_compiler = f'{prefix_path}bin/{host}-g++' + self.c_compiler = prefix_path / 'bin' / f'{host}-gcc' + self.cxx_compiler = prefix_path / 'bin' / f'{host}-g++' -def symlink_directory(src_path: str, dst_path: str, cleanup=True): - src_abspath = os.path.abspath(src_path) - dst_abspath = os.path.abspath(dst_path) - +def symlink_directory(src_path: Path, dst_path: Path, cleanup=True): if cleanup: # Delete obsolete symbolic links - for root, _, files in os.walk(dst_abspath, followlinks=True): + for root, _, files in os.walk(dst_path, followlinks=True): for filename in files: - file_path = root + os.sep + filename + file_path = Path(root) / filename - if os.path.islink(file_path) and not os.path.exists(file_path): + if file_path.is_symlink() and not file_path.exists(): os.remove(file_path) # Create symbolic links if needed - for entry in os.scandir(src_abspath): - dst_subpath = entry.path.replace(src_abspath, dst_abspath) + for entry in src_path.iterdir(): + dst_subpath = dst_path / entry.name if entry.is_dir(): os.makedirs(dst_subpath, exist_ok=True) - symlink_directory(entry.path, dst_subpath, cleanup=False) - elif not os.path.exists(dst_subpath): - if os.path.islink(entry.path): - shutil.copy(entry.path, dst_subpath, follow_symlinks=False) + symlink_directory(entry, dst_subpath, cleanup=False) + elif not dst_subpath.exists(): + if entry.is_symlink(): + shutil.copy(entry, dst_subpath, follow_symlinks=False) else: - os.symlink(entry.path, dst_subpath) + os.symlink(entry, dst_subpath) # Case insensitive dictionary class from