bootstrap-toolchain/conf/utils.py

162 lines
4.8 KiB
Python

# Toolchain builder for the Serene programming language
#
# Copyright (c) 2019-2023 Sameer Rahmani <lxsameer@gnu.org>
#
# 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 <http://www.gnu.org/licenses/>.
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)