Phase 30: complete configurable installation and release qualification
This commit is contained in:
parent
afc049e2c8
commit
90eac33a71
18 changed files with 399 additions and 59 deletions
55
tools/install_layout.py
Normal file
55
tools/install_layout.py
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
"""Shared install inventory and configurable POSIX directory layout."""
|
||||
from pathlib import Path
|
||||
|
||||
KEYS = ('bindir', 'libdir', 'includedir', 'docdir', 'licensedir', 'examplesdir', 'desktopdir', 'pkgconfigdir')
|
||||
|
||||
def arguments(parser):
|
||||
parser.add_argument('--prefix', default='/usr/local')
|
||||
parser.add_argument('--destdir', default='')
|
||||
for key in KEYS:
|
||||
parser.add_argument('--' + key)
|
||||
|
||||
|
||||
def layout(args):
|
||||
prefix = directory(args.prefix)
|
||||
defaults = dict(bindir=prefix / 'bin', libdir=prefix / 'lib', includedir=prefix / 'include',
|
||||
docdir=prefix / 'share/doc/xtc', licensedir=prefix / 'share/licenses/xtc',
|
||||
examplesdir=prefix / 'share/xtc/examples', desktopdir=prefix / 'share/applications',
|
||||
pkgconfigdir=prefix / 'lib/pkgconfig')
|
||||
return {key: directory(getattr(args, key) or value) for key, value in defaults.items()}
|
||||
|
||||
|
||||
def directory(value):
|
||||
text = str(value)
|
||||
path = Path(text)
|
||||
if not path.is_absolute() or '..' in path.parts or any(c in text for c in '\n\r\0"$\\'):
|
||||
raise ValueError('Install directories must be absolute without .., controls, quotes, $, or backslashes')
|
||||
return path
|
||||
|
||||
|
||||
def inventory(source, paths):
|
||||
entries = [('libdir', 'libxtc.a', None), ('pkgconfigdir', 'xtc.pc', None),
|
||||
('bindir', 'xtc-check', None), ('bindir', 'xtc', None),
|
||||
('desktopdir', 'xtc.desktop', source / 'packaging/xtc.desktop'),
|
||||
('licensedir', 'LICENSE', source / 'LICENSE'),
|
||||
('docdir', 'README.md', source / 'README.md'),
|
||||
('docdir', 'BINARY_MANIFEST.json', None)]
|
||||
entries += [('includedir', 'xtc/' + p.name, p) for p in sorted((source / 'include/xtc').glob('*.h'))]
|
||||
entries += [('docdir', p.name, p) for p in sorted((source / 'docs').glob('*.md'))]
|
||||
entries += [('docdir', p.name, p) for p in sorted((source / 'docs').glob('*performance*.json'))]
|
||||
entries += [('docdir', 'decisions/' + p.name, p) for p in sorted((source / 'docs/decisions').glob('*.md'))]
|
||||
entries += [('examplesdir', p.name, p) for p in sorted((source / 'examples/projects').glob('*')) if p.is_file()]
|
||||
result = [(paths[key] / name, original) for key, name, original in entries]
|
||||
if len({path for path, _ in result}) != len(result):
|
||||
raise ValueError('Install layout has overlapping file destinations')
|
||||
return result
|
||||
|
||||
|
||||
def staged(path, destdir):
|
||||
if not destdir:
|
||||
return path
|
||||
root = directory(destdir).resolve()
|
||||
result = root / path.relative_to('/')
|
||||
if not result.parent.resolve().is_relative_to(root):
|
||||
raise ValueError(f'Install directory symlink escapes DESTDIR: {result}')
|
||||
return result
|
||||
Loading…
Add table
Add a link
Reference in a new issue