Initial commit of revamped build scripts. All set to Apache License
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
# (c) 2025 by Stephan Menzel
|
||||
# Licensed under the Apache License, Version 2.0.
|
||||
# See attached file LICENSE for full details
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from common.errors import DependencyInfoError
|
||||
import common.settings
|
||||
from common.tags import sanitize_tag
|
||||
|
||||
# will be populated by build_package_tree()
|
||||
packages = {}
|
||||
|
||||
class PackageInfo:
|
||||
"""Parsed from packages.json, wraps info about each dependency"""
|
||||
version = ""
|
||||
repo = ""
|
||||
tag = ""
|
||||
dependencies = {}
|
||||
|
||||
# sbom relevant info
|
||||
name = ""
|
||||
description = None
|
||||
license_id = None
|
||||
license_name = None
|
||||
license_url = ""
|
||||
|
||||
def __init__(self, package_name: str):
|
||||
|
||||
pckjson = {}
|
||||
|
||||
with open("packages.json", "r") as jsonfile:
|
||||
pckjson = json.load(jsonfile)
|
||||
|
||||
if package_name not in pckjson:
|
||||
raise DependencyInfoError(f"Cannot find version info for {package_name} in packages.json")
|
||||
|
||||
pckdict = pckjson[package_name]
|
||||
|
||||
self.repo = pckdict["repo"]
|
||||
self.tag = pckdict["tag"]
|
||||
self.version = pckdict["version"]
|
||||
self.dependencies = {}
|
||||
|
||||
if "depends" in pckdict:
|
||||
for dependency in pckdict["depends"]:
|
||||
if dependency not in packages:
|
||||
packages[dependency] = PackageInfo(dependency)
|
||||
self.dependencies[dependency] = packages[dependency]
|
||||
|
||||
# Save some data to later generate the SBOM with
|
||||
self.name = package_name
|
||||
self.description = pckdict["description"] if "description" in pckdict else None
|
||||
if "license_id" in pckdict:
|
||||
self.license_id = pckdict["license_id"]
|
||||
else:
|
||||
self.license_name = pckdict["license_name"]
|
||||
self.license_url = pckdict["license_url"]
|
||||
|
||||
def dependency_path(self, package_name: str) -> Path:
|
||||
"""Give the path underneath which the package, according to its version, is installed"""
|
||||
if package_name not in self.dependencies:
|
||||
raise DependencyInfoError(f"Cannot find dependency {package_name} in {self.name}.")
|
||||
return self.dependencies[package_name].install_location()
|
||||
|
||||
def bom_ref(self) -> str:
|
||||
"""Return the CycloneDX bom-ref for this package"""
|
||||
return f"{self.name}=={self.version}"
|
||||
|
||||
def purl(self) -> str:
|
||||
"""Return the CycloneDX purl for this package"""
|
||||
return f"pkg:cmake/{self.name}@{self.version}"
|
||||
|
||||
def add_to_sbom(self, sbom: dict) -> None:
|
||||
"""Add all information we have about this package to a CycloneDX SBOM"""
|
||||
|
||||
if "components" not in sbom:
|
||||
sbom["components"] = []
|
||||
|
||||
license = {
|
||||
"acknowledgement": "concluded",
|
||||
"url": self.license_url
|
||||
}
|
||||
|
||||
if self.license_id:
|
||||
license["id"] = self.license_id
|
||||
else:
|
||||
license["name"] = self.license_name
|
||||
|
||||
sbom["components"].append({
|
||||
"name": self.name,
|
||||
"purl": self.purl(),
|
||||
"type": "library",
|
||||
"version": self.version,
|
||||
"bom-ref": self.bom_ref(),
|
||||
"description": self.description,
|
||||
"externalReferences": [
|
||||
{
|
||||
"comment": "from packaging metadata Project-URL: Source Code",
|
||||
"type": "other",
|
||||
"url": self.repo,
|
||||
},
|
||||
],
|
||||
"licenses": [
|
||||
{
|
||||
"license": license
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
if "dependencies" not in sbom:
|
||||
sbom["dependencies"] = []
|
||||
|
||||
dependencies_entry = {"ref": self.purl()}
|
||||
for name, dep_info in self.dependencies.items():
|
||||
if "dependsOn" not in dependencies_entry:
|
||||
dependencies_entry["dependsOn"] = []
|
||||
dependencies_entry["dependsOn"].append(dep_info.purl())
|
||||
sbom["dependencies"].append(dependencies_entry)
|
||||
|
||||
def install_location(self) -> Path:
|
||||
"""Get the directory where this package out to be installed in
|
||||
"""
|
||||
return common.settings.install_prefix / Path(f"{self.name}-{self.version}")
|
||||
|
||||
def src_dir(self) -> Path:
|
||||
"""Get us the directory where the source is going to be checked out in (a subdir under "raw" normally)
|
||||
"""
|
||||
return common.settings.build_dir / Path(f"{self.name}-{sanitize_tag(self.tag)}")
|
||||
|
||||
|
||||
def build_package_tree() -> None:
|
||||
"""Assemble the global dependency tree of packages known to that system
|
||||
"""
|
||||
global packages
|
||||
pckjson = {}
|
||||
with open("packages.json", "r") as jsonfile:
|
||||
pckjson = json.load(jsonfile)
|
||||
|
||||
for package_name in pckjson.keys():
|
||||
if package_name not in packages:
|
||||
packages[package_name] = PackageInfo(package_name)
|
||||
|
||||
|
||||
def get_package_info(name: str) -> PackageInfo:
|
||||
"""Get the PackageInfo struct of that name or
|
||||
|
||||
:throws DependencyInfoError
|
||||
"""
|
||||
global packages
|
||||
|
||||
if name not in packages:
|
||||
raise DependencyInfoError(f"No build info for {name}")
|
||||
|
||||
return packages[name]
|
||||
Reference in New Issue
Block a user