# Toolchain builder for the Serene programming language # # Copyright (c) 2019-2023 Sameer Rahmani # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, version 2. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import os import contextlib import shutil from pathlib import Path class current_dir: def __init__(self, path): self.current = os.getcwd() self.target = path def __enter__(self): print(f"Entering dir: {self.target} from: {self.current}") os.chdir(self.target) return self def __exit__(self, exc_type, exc_value, exc_traceback): print(f"Exiting dir: {self.target}") os.chdir(self.current) def get_version(pkg_name): env = os.environ.get(f"{pkg_name.upper()}_VERSION") if not env: raise ValueError( f"""Can't find the version for {pkg_name}! Did you forget to define the '{pkg_name.upper()}_VERSION' in the builder?""" ) return env def copy_tree(src, dst, preserve_symlinks=True, ignore=None): src = Path(src) dst = Path(dst) dst.mkdir(exist_ok=True, parents=True) for item in src.iterdir(): skip_this = False if ignore: for pattern in ignore: if fnmatch(item.name, pattern): skip_this = True break if skip_this: continue if item.is_dir(): copy_tree( item, dst / item.name, preserve_symlinks, ignore, ) elif item.is_file() or item.is_symlink: try: shutil.copy2( item, dst / item.name, follow_symlinks=not preserve_symlinks ) except Exception as e: if not item.is_symlink: raise e def with_static_flags(cmake_vars={}): cmake_vars["CMAKE_C_FLAGS"] = f"-static {cmake_vars.get('CMAKE_C_FLAGS', '')}" cmake_vars["CMAKE_CXX_FLAGS"] = f"-static {cmake_vars.get('CMAKE_CXX_FLAGS', '')}" cmake_vars[ "CMAKE_EXE_LINKER_FLAGS_INIT" ] = f"-static {cmake_vars.get('CMAKE_EXE_LINKER_FLAGS_INIT', '')}" return cmake_vars def with_musl_toolchain(conanfile, tc, sysroot=None, envname="TARGET"): target = os.environ[envname] opts = { "CMAKE_SYSTEM_NAME": "Linux", "CMAKE_C_COMPILER": "clang", "CMAKE_CXX_COMPILER": "clang++", "CMAKE_ASM_COMPILER": "clang", "CMAKE_C_COMPILER_TARGET": target, # "CMAKE_C_FLAGS": f"--target={target}", "CMAKE_CXX_COMPILER_TARGET": target, # "CMAKE_CXX_FLAGS": f"--target={target}", "CMAKE_ASM_COMPILER_TARGET": target, # "CMAKE_ASM_FLAGS": f"--target={target}", } if sysroot: opts.update( { "CMAKE_SYSROOT": sysroot, "CMAKE_DEFAULT_SYSROOT": sysroot, "CMAKE_FIND_ROOT_PATH": sysroot, "CMAKE_FIND_ROOT_PATH_MODE_PROGRAM": "BOTH", "CMAKE_FIND_ROOT_PATH_MODE_LIBRARY": "ONLY", "CMAKE_FIND_ROOT_PATH_MODE_INCLUDE": "ONLY", "CMAKE_FIND_ROOT_PATH_MODE_PACKAGE": "ONLY", } ) for k, v in opts.items(): tc.variables[k] = v def copy_template(conanfile, src, dest, varmap): result = Path(src).read_text() target_file = Path(dest) for k, v in varmap.items(): print(f">> replacing @{k}@ with {str(v)}") result = result.replace(f"@{k}@", str(v)) target_file.write_text(result) def copy_dependency_tree(conanfile, dependencies_to_copy=[], dest=None): root = Path(conanfile.package_folder) if dest: root = Path(dest) for dependency in dependencies_to_copy: conanfile.output.info(f"Copy the tree of '{dependency}' to '{root}'") dep = Path(conanfile.dependencies[dependency].package_folder) for dir_path in ["include", "lib", "bin", "share"]: try: copy_tree(dep / dir_path, root / dir_path) except FileNotFoundError: conanfile.output.info( f"Dir '{dep / dir_path}' does not exist, skipping" ) @contextlib.contextmanager def chpath(path: Path) -> None: """ Changes working directory and returns to previous on exit. """ prev_cwd = Path.cwd() os.chdir(path) try: yield finally: os.chdir(prev_cwd)