Files
fds-os/tools/rust-notices
T
2026-09-21 22:29:23 +08:00

46 lines
2.2 KiB
Python
Executable File

#!/usr/bin/env python3
"""Collect license notices for the locked ARM Rust workspace and vendored C code."""
import argparse
import hashlib
import json
from pathlib import Path
import subprocess
project = Path(__file__).resolve().parents[1]
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('output', type=Path)
args = parser.parse_args()
metadata = json.loads(subprocess.check_output([
'cargo', 'metadata', '--locked', '--offline', '--format-version', '1',
'--filter-platform', 'aarch64-unknown-linux-musl',
], cwd=project))
resolved = {node['id'] for node in metadata['resolve']['nodes']}
notices = ['FDS/OS Rust workspace third-party notices\n',
'Includes build dependencies and vendored native-code license files.\n',
'This inventory does not imply every dependency is linked into every executable.\n']
count = 0
for package in sorted(metadata['packages'], key=lambda p: (p['name'], p['version'])):
if not package['source'] or package['id'] not in resolved:
continue
root = Path(package['manifest_path']).parent
files = {path for path in root.rglob('*') if path.is_file()
and path.name.upper().startswith(('LICENSE', 'COPYING', 'NOTICE'))}
if package['license_file']:
files.add(root / package['license_file'])
if not files:
parser.error(f'No license notice found for {package["name"]} {package["version"]}')
notices.append(f'\n=== {package["name"]} {package["version"]} ===\n'
f'Declared license: {package["license"] or "see license file"}\n'
f'Source: {package["source"]}\n')
for path in sorted(files):
if path.is_symlink() or not path.resolve().is_relative_to(root.resolve()):
parser.error(f'License notice leaves crate source: {package["name"]}')
data = path.read_bytes()
notices.append(f'\n--- {path.relative_to(root)} ---\n'
f'SHA-256: {hashlib.sha256(data).hexdigest()}\n\n')
notices.append(data.decode('utf-8') + '\n')
count += 1
with args.output.open('x') as stream:
stream.write(''.join(notices))
print(f'PASS: license notices for {count} resolved third-party crates: {args.output}')