162 lines
4.8 KiB
Python
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)
|