#!/usr/bin/env python3 # (c) 2025 by Stephan Menzel # Licensed under the Apache License, Version 2.0. # See attached file LICENSE for full details import argparse import json import os import datetime import logging as log import importlib from build_functions.build_ecal import build_ecal from build_functions.build_ecaludp import build_ecaludp from build_functions.build_ftxui import build_ftxui from build_functions.build_abseil import build_abseil from build_functions.build_asio import build_asio from build_functions.build_boost import build_boost from build_functions.build_cares import build_cares from build_functions.build_ceres import build_ceres from build_functions.build_curl import build_curl from build_functions.build_cppzmq import build_cppzmq from build_functions.build_eigen import build_eigen from build_functions.build_fineftp import build_fineftp from build_functions.build_glog import build_glog from build_functions.build_googletest import build_googletest from build_functions.build_grpc import build_grpc from build_functions.build_hdf5 import build_hdf5 from build_functions.build_jpeg import build_jpeg from build_functions.build_libzmq import build_libzmq from build_functions.build_matplot import build_matplot from build_functions.build_onetbb import build_onetbb from build_functions.build_opencv import build_opencv from build_functions.build_openssl import build_openssl from build_functions.build_opensubdiv import build_opensubdiv from build_functions.build_openusd import build_openusd from build_functions.build_pcapplusplus import build_pcapplusplus from build_functions.build_protobuf import build_protobuf from build_functions.build_qt5 import build_qt5 from build_functions.build_qt6 import build_qt6 from build_functions.build_qwt import build_qwt from build_functions.build_recycle import build_recycle from build_functions.build_spdlog import build_spdlog from build_functions.build_tclap import build_tclap from build_functions.build_re2 import build_re2 from build_functions.build_tcp_pubsub import build_tcp_pubsub from build_functions.build_termcolor import build_termcolor from build_functions.build_tinyxml2 import build_tinyxml2 from build_functions.build_udpcap import build_udpcap from build_functions.build_yaml_cpp import build_yaml_cpp from build_functions.build_zlib import build_zlib import common.settings from package.package_info import PackageInfo, get_package_info, build_package_tree import sys from pathlib import Path from common.errors import DependencyInfoError from build_functions.build_utils import print_banner, file_and_console_log, logfile # Iterate over all Python files in the `build_functions` folder and import them module_path = Path(__file__).parent / "build_functions" for file in module_path.glob("*.py"): module_name = f"build_functions.{file.stem}" module = importlib.import_module(module_name) # If the module has a `build` function, call it if hasattr(module, "build"): module.build() # Plenty of warnings raising out of protobuf when using c++23 os.environ["CXXFLAGS"] = "-D_SILENCE_ALL_CXX23_DEPRECATION_WARNINGS" def build_all(prefix: Path | str) -> dict: """Build all known dependencies :return The merged (partial) SBOM :raise DependencyInfoError """ sbom = {} file_and_console_log(f"Build script running in python {sys.version}") file_and_console_log(f"Installing to: {prefix}") # First those without any dependencies build_abseil(prefix, sbom) build_asio(prefix, sbom) build_boost(prefix, sbom) build_cares(prefix, sbom) build_ftxui(prefix, sbom) build_glog(prefix, sbom) build_eigen(prefix, sbom) build_libzmq(prefix, sbom) build_jpeg(prefix, sbom) build_onetbb(prefix, sbom) # build_pcapplusplus(prefix, sbom) build_spdlog(prefix, sbom) build_tclap(prefix, sbom) build_recycle(prefix, sbom) build_termcolor(prefix, sbom) build_tinyxml2(prefix, sbom) build_yaml_cpp(prefix, sbom) build_zlib(prefix, sbom) # Conditional. This could depend on abseil but I'll try to build without build_googletest(prefix, sbom) # Then the ones that depend on any of those above # Note that this doesn't constitute a dependency tree yet build_curl(prefix, sbom) build_ecaludp(prefix, sbom) build_fineftp(prefix, sbom) build_re2(prefix, sbom) build_cppzmq(prefix, sbom) build_protobuf(prefix, sbom) build_ceres(prefix, sbom) build_opencv(prefix, sbom) build_matplot(prefix, sbom) build_openssl(prefix, sbom) build_opensubdiv(prefix, sbom) build_openusd(prefix, sbom) build_hdf5(prefix, sbom) build_tcp_pubsub(prefix, sbom) # build_udpcap(prefix, sbom) # This one gets a special place as it depends on many of the above build_grpc(prefix, sbom) build_qt5(prefix, sbom) build_qt6(prefix, sbom) build_qwt(prefix, sbom) build_ecal(prefix, sbom) return sbom build_functions = { "abseil-cpp": build_abseil, "asio": build_asio, "boost": build_boost, "ceres-solver": build_ceres, "curl": build_curl, "glog": build_glog, "hdf5": build_hdf5, "protobuf": build_protobuf, "ecal": build_ecal, "ecaludp": build_ecaludp, "eigen": build_eigen, "libzmq": build_libzmq, "cppzmq": build_cppzmq, "fineftp": build_fineftp, "ftxui": build_ftxui, "googletest": build_googletest, "libjpeg-turbo": build_jpeg, "opencv": build_opencv, "matplotplusplus": build_matplot, "openssl": build_openssl, "opensubdiv": build_opensubdiv, "openusd": build_openusd, "onetbb": build_onetbb, "pcapplusplus": build_pcapplusplus, "re2": build_re2, "recycle": build_recycle, "spdlog": build_spdlog, "tclap": build_tclap, "c-ares": build_cares, "grpc": build_grpc, "qt5": build_qt5, "qt6": build_qt6, "qwt": build_qwt, "termcolor": build_termcolor, "tcp_pubsub": build_tcp_pubsub, "tinyxml2": build_tinyxml2, "udpcap": build_udpcap, "yaml-cpp": build_yaml_cpp, "zlib": build_zlib, } if __name__ == '__main__': try: with open(logfile, 'w') as f: f.write(str(datetime.datetime.now()) + f' - started {__file__}\n') parser = argparse.ArgumentParser() parser.add_argument("--install-dir", "-i", type=str, required=True, help="install into this directory") parser.add_argument("--package", "-p", type=str, default="all", help="build specific package or 'all'") parser.add_argument("--rebuild", action="store_true", help="always delete build dir") parser.add_argument("--sbom", "-s", type=str, default="sbom.json", help="Append to this SBOM in CycloneDX format. If all packages are being built (-p=all) " "a previously existing sbom file gets deleted and overwritten") parser.add_argument("--build-dir", "-b", type=Path, default=Path("raw"), help="use this directory to build in") args = parser.parse_args() global_prefix = Path(args.install_dir) if not global_prefix.is_absolute(): script_dir = Path(__file__).parent.resolve().absolute() global_prefix = script_dir / global_prefix common.settings.set_global_build_dir(args.build_dir) common.settings.set_global_install_prefix(args.install_dir) common.settings.set_global_rebuild(args.rebuild) package = args.package sbomfile = args.sbom build_package_tree() if package == "all": # Build all packages sbom = build_all(prefix=global_prefix) # (Over)write CycloneDX SBOM with open(sbomfile, "w") as f: json.dump(sbom, f) else: if package not in build_functions: raise DependencyInfoError(f"Don't know how to build {package}") sbom = {} # Build the package, amend SBOM with package info build_functions[package](prefix=global_prefix, sbom=sbom) # The partial SBOM gets written into the install dir so we can later combine it. # We cannot merge them into one file right here as in the pipeline there may be multiple tasks in parallel package_info = get_package_info(package) partial_sbom_filename = package_info.install_location() / "partial_sbom.json" with open(partial_sbom_filename, "w") as f: json.dump(sbom, f) print_banner("Done") exit(0) except ValueError as ve: print(f"Cannot read or write SBOM: {str(ve)}") except DependencyInfoError as die: print(f"Dependency info error: {str(die)}") exit(-1)