diff --git a/mlonmcu/setup/tasks/__init__.py b/mlonmcu/setup/tasks/__init__.py index 215db2fc1..1fe8c5437 100644 --- a/mlonmcu/setup/tasks/__init__.py +++ b/mlonmcu/setup/tasks/__init__.py @@ -38,3 +38,5 @@ from .utvmcg import * # noqa: F401, F403 from .zephyr import * # noqa: F401, F403 from .pulp import * # noqa: F401, F403 +from .boost import * # noqa: F401, F403 +from .cmake import * # noqa: F401, F403 diff --git a/mlonmcu/setup/tasks/boost.py b/mlonmcu/setup/tasks/boost.py new file mode 100644 index 000000000..9039275d4 --- /dev/null +++ b/mlonmcu/setup/tasks/boost.py @@ -0,0 +1,108 @@ +# +# Copyright (c) 2022 TUM Department of Electrical and Computer Engineering. +# +# This file is part of MLonMCU. +# See https://github.com/tum-ei-eda/mlonmcu.git for further info. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""Definition of tasks used to dynamically install MLonMCU dependencies""" + +import os +import multiprocessing +from pathlib import Path + +from mlonmcu.setup.task import TaskType +from mlonmcu.context.context import MlonMcuContext +from mlonmcu.setup import utils +from mlonmcu.logging import get_logger + +from .common import get_task_factory + +logger = get_logger() + +Tasks = get_task_factory() + + +def _validate_boost(context: MlonMcuContext, params=None): + if context.environment.has_target("spike") or context.environment.has_target("etiss_pulpino"): + return True + return False + + +@Tasks.provides(["boost.src_dir"]) +@Tasks.validate(_validate_boost) +@Tasks.register(category=TaskType.MISC) +def download_boost( + context: MlonMcuContext, params=None, rebuild=False, verbose=False, threads=multiprocessing.cpu_count() +): + """Fetch the boost library sources.""" + user_vars = context.environment.vars + version = user_vars.get("boost.version", "1.81.0") + # flags = utils.makeFlags((True, version)) + flags = [] + boostName = utils.makeDirName("boost", flags=flags) + boostSrcDir = context.environment.paths["deps"].path / "src" / boostName + if "boost.install_dir" in user_vars: + return False + if rebuild or not utils.is_populated(boostSrcDir): + if "boost.dl_url" in user_vars: + boostUrl = user_vars["boost.dl_url"] + boostUrl, boostArchive = boostUrl.rsplit("/", 1) + else: + boostUrl = f"https://boostorg.jfrog.io/artifactory/main/release/{version}/source/" + version_ = version.replace(".", "_") + boostArchive = f"boost_{version_}.tar.gz" # zip does not preserve file permissions + utils.download_and_extract(boostUrl, boostArchive, boostSrcDir, progress=verbose) + context.cache["boost.src_dir"] = boostSrcDir + + +@Tasks.needs(["boost.src_dir"]) +@Tasks.provides(["boost.install_dir"]) +@Tasks.validate(_validate_boost) +@Tasks.register(category=TaskType.MISC) +def build_boost( + context: MlonMcuContext, params=None, rebuild=False, verbose=False, threads=multiprocessing.cpu_count() +): + """Build boost library.""" + flags = [] + boostName = utils.makeDirName("boost", flags=flags) + boostSrcDir = context.cache["boost.src_dir"] + # boostBuildDir = context.environment.paths["deps"].path / "build" / boostName + boostBuildDir = boostSrcDir + boostInstallDir = context.environment.paths["deps"].path / "install" / boostName + user_vars = context.environment.vars + if "boost.install_dir" in user_vars: + return False + if rebuild or not utils.is_populated(boostInstallDir): + bootstrapArgs = ["--with-libraries=log,thread,system,filesystem,program_options,test", f"--prefix={boostInstallDir}"] + # env = os.environ.copy() + utils.mkdirs(boostBuildDir) + utils.exec_getout( + "sh", + str(boostSrcDir / "bootstrap.sh"), + *bootstrapArgs, + cwd=boostBuildDir, + # env=env, + live=False, + print_output=False, + ) + utils.exec_getout( + str(boostBuildDir / "b2"), + "install", + cwd=boostBuildDir, + # env=env, + live=False, + print_output=False, + ) + context.cache["boost.install_dir"] = boostBuildDir diff --git a/mlonmcu/setup/tasks/cmake.py b/mlonmcu/setup/tasks/cmake.py new file mode 100644 index 000000000..cd94527db --- /dev/null +++ b/mlonmcu/setup/tasks/cmake.py @@ -0,0 +1,118 @@ +# +# Copyright (c) 2022 TUM Department of Electrical and Computer Engineering. +# +# This file is part of MLonMCU. +# See https://github.com/tum-ei-eda/mlonmcu.git for further info. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""Definition of tasks used to dynamically install MLonMCU dependencies""" + +import os +import multiprocessing +from pathlib import Path + +from mlonmcu.setup.task import TaskType +from mlonmcu.context.context import MlonMcuContext +from mlonmcu.setup import utils +from mlonmcu.logging import get_logger + +from .common import get_task_factory + +logger = get_logger() + +Tasks = get_task_factory() + + +def _validate_cmake(context: MlonMcuContext, params=None): + if context.environment.has_platform("mlif"): + return True + if context.environment.has_framework("tvm"): + return True + if context.environment.has_platform("microtvm"): + return True + if context.environment.has_platform("espidf"): + return True + if context.environment.has_platform("zephyr"): + return True + if context.environment.has_feature("muriscvnn"): + return True + if context.environment.has_backend("tflmc"): + return True + if context.environment.has_backend("utvmcg"): + return True + if context.environment.has_backend("etiss_pulpino"): + return True + return False + + +@Tasks.provides(["cmake.src_dir"]) +@Tasks.validate(_validate_cmake) +@Tasks.register(category=TaskType.MISC) +def download_cmake( + context: MlonMcuContext, params=None, rebuild=False, verbose=False, threads=multiprocessing.cpu_count() +): + """Fetch the cmake sources.""" + user_vars = context.environment.vars + version = user_vars.get("cmake.version", "3.25.2") + # flags = utils.makeFlags((True, version)) + flags = [] + cmakeName = utils.makeDirName("cmake", flags=flags) + cmakeSrcDir = context.environment.paths["deps"].path / "src" / cmakeName + if "cmake.exe" in user_vars: + return False + if rebuild or not utils.is_populated(cmakeSrcDir): + if "cmake.dl_url" in user_vars: + cmakeUrl = user_vars["boost.dl_url"] + cmakeUrl, cmakeArchive = cmakeUrl.rsplit("/", 1) + else: + cmakeUrl = f"https://github.com/Kitware/CMake/releases/download/v{version}/" + cmakeArchive = f"cmake-{version}.tar.gz" + # TODO: windows/macos support? + utils.download_and_extract(cmakeUrl, cmakeArchive, cmakeSrcDir, progress=verbose) + context.cache["cmake.src_dir"] = cmakeSrcDir + + +@Tasks.needs(["cmake.src_dir"]) +@Tasks.provides(["cmake.install_dir", "cmake.exe"]) +@Tasks.validate(_validate_cmake) +@Tasks.register(category=TaskType.MISC) +def build_cmake( + context: MlonMcuContext, params=None, rebuild=False, verbose=False, threads=multiprocessing.cpu_count() +): + """Build cmake tool.""" + flags = [] + cmakeName = utils.makeDirName("cmake", flags=flags) + cmakeSrcDir = context.cache["cmake.src_dir"] + cmakeBuildDir = context.environment.paths["deps"].path / "build" / cmakeName + # boostBuildDir = boostSrcDir + cmakeInstallDir = context.environment.paths["deps"].path / "install" / cmakeName + cmakeExe = cmakeInstallDir / "bin" / "cmake" + user_vars = context.environment.vars + if "cmake.exe" in user_vars: + return False + if rebuild or not utils.is_populated(cmakeInstallDir) or not utils.is_file(cmakeExe): + bootstrapArgs = [f"--prefix={cmakeInstallDir}", "--", "-DCMAKE_USE_OPENSSL=OFF"] + # env = os.environ.copy() + utils.mkdirs(cmakeBuildDir) + utils.exec_getout( + str(cmakeSrcDir / "bootstrap"), + *bootstrapArgs, + cwd=cmakeBuildDir, + # env=env, + live=False, + print_output=False, + ) + utils.make("install", cwd=cmakeBuildDir, threads=threads, live=verbose) + context.cache["cmake.install_dir"] = cmakeBuildDir + context.cache["cmake.exe"] = cmakeExe diff --git a/mlonmcu/setup/tasks/spike.py b/mlonmcu/setup/tasks/spike.py index 5f5615f64..8fcbe47eb 100644 --- a/mlonmcu/setup/tasks/spike.py +++ b/mlonmcu/setup/tasks/spike.py @@ -149,7 +149,7 @@ def clone_spike( context.cache["spike.src_dir"] = spikeSrcDir -@Tasks.needs(["spike.src_dir", "riscv_gcc.install_dir", "riscv_gcc.name"]) +@Tasks.needs(["spike.src_dir", "riscv_gcc.install_dir", "riscv_gcc.name", "boost.install_dir"]) @Tasks.provides(["spike.build_dir", "spike.exe"]) @Tasks.validate(_validate_spike) @Tasks.register(category=TaskType.TARGET)