Commit 40360bda authored by Andreas Bombe's avatar Andreas Bombe

Remove update-ghdl-libraries and associated configuration for now

As the way libraries are organized has changed between ghdl 0.35 and
the git snapshot now packaged, update-ghdl-libraries won't work without
changes. In fact, the changes would make it easier to organize but at
this point let's get ghdl back into the archive without this feature
and design it back in later.

This also changes library handling in the way that the standard
libraries are again prebuilt and installed with the package.
parent 0a56ae30
......@@ -24,35 +24,6 @@ invalid, the wrapper will silently revert to selecting the first installed
backend it finds.
Creating packages or local installations of system-wide VHDL libraries
======================================================================
These packages ship with the IEEE standard library sources in subdirectories of
/usr/lib/ghdl/src and configuration files controlling compilation in
/usr/lib/ghdl/config. Libraries are compiled automatically upon installation or
upgrades of involved packages and can also be manually executed by running
update-ghdl-libraries.
Debian packages installing additional libraries for GHDL should install the
sources into subdirs of /usr/lib/ghdl/src and associated configuration files
into /usr/lib/ghdl/config. When required, configuration files can be
alternatively installed into /usr/lib/ghdl/config-override. Files in that
directory override files of the same name in the global config directory.
Installing these files is sufficient, dpkg triggers will take care of
recompilation happening as required.
Local, unpackaged libraries can be installed into /usr/local/lib/ghdl/src and
their configuration files into /usr/local/lib/ghdl/config. These configuration
files will override files of the same name in both the previously mentioned
config directories. After installing or updating local libraries,
update-ghdl-libraries must be called manually to compile them. However, if
update-ghdl-libraries is run automatically due to package updates, the local
libraries will be included in the compilation.
NOTE that the organization of libraries and the configuration file format are
still in development and the above isn't fully functional yet.
Build profiles
==============
......
......@@ -8,8 +8,6 @@ ghdl (0.35+git20180503+dfsg-1) UNRELEASED; urgency=medium
* Add build profiles to skip building any of the backends
* New /usr/bin/ghdl wrapper script that executes an installed ghdl backend
variant depending on an environment variable or automatic selection
* Add program update-ghdl-libraries and maintainer script scaffolding to
facilitate packaged and locally installed third-party VHDL libraries
* Rewrite debian/copyright, change to machine-readable format
* Change debian/watch to current upstream on GitHub
* Change source format to 3.0 (quilt)
......
......@@ -22,7 +22,7 @@ Vcs-Git: https://salsa.debian.org/electronics-team/ghdl/ghdl.git
Package: ghdl
Architecture: any
Depends: ghdl-mcode | ghdl-gcc | ghdl-llvm, python3, ${misc:Depends}
Depends: ghdl-mcode | ghdl-gcc | ghdl-llvm, ${misc:Depends}
Suggests: gtkwave
Description: VHDL compiler/simulator
GHDL is a compiler and simulator for VHDL, a Hardware Description Language.
......
usr/lib/ghdl/gcc/v87
usr/lib/ghdl/gcc/v93
usr/lib/ghdl/gcc/v08
package-contains-empty-directory usr/lib/ghdl/gcc/v87/
package-contains-empty-directory usr/lib/ghdl/gcc/v93/
package-contains-empty-directory usr/lib/ghdl/gcc/v08/
# Yes, the company is really called Synopsys
spelling-error-in-binary usr/bin/ghdl-gcc synopsys synopsis
spelling-error-in-binary usr/lib/ghdl/gcc/libexec/gcc/*/ghdl1 synopsys synopsis
......
#!/bin/sh
backend=gcc
set -e
update_libraries() {
if which update-ghdl-libraries >/dev/null; then
update-ghdl-libraries --backend=$backend
fi
}
if [ "$1" = "triggered" ]; then
update_libraries
exit 0
fi
#DEBHELPER#
if [ "$1" = "configure" ]; then
update_libraries
fi
#!/bin/sh
backend=gcc
set -e
if [ "$1" = "remove" ]; then
if which update-ghdl-libraries >/dev/null; then
update-ghdl-libraries --cleanup --backend=$backend
fi
fi
#DEBHELPER#
interest-noawait /usr/lib/ghdl/config
interest-noawait /usr/lib/ghdl/config-override
usr/lib/ghdl/llvm/v87
usr/lib/ghdl/llvm/v93
usr/lib/ghdl/llvm/v08
package-contains-empty-directory usr/lib/ghdl/llvm/v87/
package-contains-empty-directory usr/lib/ghdl/llvm/v93/
package-contains-empty-directory usr/lib/ghdl/llvm/v08/
# Yes, the company is really called Synopsys
spelling-error-in-binary usr/bin/ghdl-llvm synopsys synopsis
spelling-error-in-binary usr/lib/ghdl/llvm/ghdl1-llvm synopsys synopsis
......
#!/bin/sh
backend=llvm
set -e
update_libraries() {
if which update-ghdl-libraries >/dev/null; then
update-ghdl-libraries --backend=$backend
fi
}
if [ "$1" = "triggered" ]; then
update_libraries
exit 0
fi
#DEBHELPER#
if [ "$1" = "configure" ]; then
update_libraries
fi
#!/bin/sh
backend=llvm
set -e
if [ "$1" = "remove" ]; then
if which update-ghdl-libraries >/dev/null; then
update-ghdl-libraries --cleanup --backend=$backend
fi
fi
#DEBHELPER#
interest-noawait /usr/lib/ghdl/config
interest-noawait /usr/lib/ghdl/config-override
usr/lib/ghdl/mcode/v87
usr/lib/ghdl/mcode/v93
usr/lib/ghdl/mcode/v08
package-contains-empty-directory usr/lib/ghdl/mcode/v87/
package-contains-empty-directory usr/lib/ghdl/mcode/v93/
package-contains-empty-directory usr/lib/ghdl/mcode/v08/
# Yes, the company is really called Synopsys
spelling-error-in-binary usr/bin/ghdl-mcode synopsys synopsis
spelling-error-in-copyright Synopsys Synopsis
#!/bin/sh
backend=mcode
set -e
update_libraries() {
if which update-ghdl-libraries >/dev/null; then
update-ghdl-libraries --backend=$backend
fi
}
if [ "$1" = "triggered" ]; then
update_libraries
exit 0
fi
#DEBHELPER#
if [ "$1" = "configure" ]; then
update_libraries
fi
#!/bin/sh
backend=mcode
set -e
if [ "$1" = "remove" ]; then
if which update-ghdl-libraries >/dev/null; then
update-ghdl-libraries --cleanup --backend=$backend
fi
fi
#DEBHELPER#
interest-noawait /usr/lib/ghdl/config
interest-noawait /usr/lib/ghdl/config-override
usr/lib/ghdl/config-override
usr/bin/ghdl
usr/lib/ghdl/src
usr/lib/ghdl/include
debian/update-ghdl-libraries usr/sbin
debian/*.ghdllib usr/lib/ghdl/config
package-contains-empty-directory usr/lib/ghdl/config-override/
# Yes, the company is really called Synopsys
spelling-error-in-copyright Synopsys Synopsis
doc/ghdl.1
debian/update-ghdl-libraries.8
[library]
name = ieee
subdir = ieee
depends = std
standards = 87 93
[compile]
[compile 87]
sources = openieee/std_logic_1164.v87 openieee/std_logic_1164-body.v87
openieee/numeric_bit.v87 openieee/numeric_bit-body.v87
openieee/numeric_std.v87 openieee/numeric_std-body.v87
[compile 93]
sources = openieee/std_logic_1164.v93 openieee/std_logic_1164-body.v93
openieee/numeric_bit.v93 openieee/numeric_bit-body.v93
openieee/numeric_std.v93 openieee/numeric_std-body.v93
openieee/math_real.vhdl openieee/math_real-body.vhdl
Description: Add install-only targets to libraries/Makefile.inc
The Debian packages do not install compiled libraries, so these targets allow
installing the files without compilation.
Author: Andreas Bombe <aeb@debian.org>
Last-Update: 2018-01-12
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
Index: git/libraries/Makefile.inc
===================================================================
--- git.orig/libraries/Makefile.inc 2018-05-12 23:33:48.340773255 +0200
+++ git/libraries/Makefile.inc 2018-05-12 23:33:48.336773258 +0200
@@ -356,3 +356,21 @@
libs.vhdl.standard: $(STD93_DIR)/std_standard.o \
$(STD87_DIR)/std_standard.o \
$(STD08_DIR)/std_standard.o
+
+
+##############################################################################
+#
+# Installation without compilation targets used in Debian packaging
+#
+##############################################################################
+install-directories:
+ mkdir -p $(LIBDST_DIR)/src/openieee
+ mkdir -p $(LIBDST_DIR)/src/std
+ mkdir -p $(LIBDST_DIR)/src/synopsys
+
+install-source: install-directories \
+ $(STD87_SRCS) $(STD93_SRCS) $(STD08_SRCS) \
+ $(IEEE87_SRCS) $(IEEE93_SRCS) \
+ $(SYNOPSYS87_SRCS) $(SYNOPSYS93_SRCS) $(SYNOPSYS08_SRCS)
+
+.PHONY: install-directories install-source
versioning
fix-build
lib-install-targets
modify-install-paths
adjust-compile-flags
extend-ghdl-manpage
......@@ -43,8 +43,7 @@ export CC
dh ${@}
override_dh_auto_configure:
mkdir $(BUILDDIR)
mkdir $(BUILDDIR)/mcode $(BUILDDIR)/llvm $(BUILDDIR)/gcc
mkdir -p $(BUILDDIR)/mcode $(BUILDDIR)/llvm $(BUILDDIR)/gcc
@echo
@echo ------------------------------------------------------------
@echo Configuring with mcode backend
......@@ -97,14 +96,14 @@ override_dh_auto_build:
@echo Building with mcode backend
@echo ------------------------------------------------------------
if [ -n "$(WITH_MCODE)" ]; then \
$(MAKE) -C $(BUILDDIR)/mcode ghdl_mcode all.vpi; \
$(MAKE) -C $(BUILDDIR)/mcode; \
fi
@echo
@echo ------------------------------------------------------------
@echo Building with llvm backend
@echo ------------------------------------------------------------
if [ -n "$(WITH_LLVM)" ]; then \
$(MAKE) -C $(BUILDDIR)/llvm ghdl_llvm ghdl1-llvm grt-all all.vpi; \
$(MAKE) -C $(BUILDDIR)/llvm; \
fi
@echo
@echo ------------------------------------------------------------
......@@ -113,29 +112,26 @@ override_dh_auto_build:
if [ -n "$(WITH_GCC)" ]; then \
$(MAKE) $(MAKEPARALLEL) -C $(BUILDDIR)/gcc/gccbuild; \
$(MAKE) -C $(BUILDDIR)/gcc lib/ghdl/gcc/libgrt.a all.vpi; \
$(MAKE) -C $(BUILDDIR)/gcc ghdllib \
GHDL_GCC_BIN=$(BUILDDIR)/gcc/gccbuild/gcc/ghdl \
GHDL1_GCC_BIN="--GHDL1=$(BUILDDIR)/gcc/gccbuild/gcc/ghdl1"; \
fi
override_dh_auto_install:
install -pD debian/ghdl.wrapper $(CURDIR)/debian/tmp/usr/bin/ghdl
# we only need the library sources, install them using our patched-in target
$(MAKE) -j1 -f libraries/Makefile.inc install-source \
LIBDST_DIR=$(CURDIR)/debian/tmp/usr/lib/ghdl LIBSRC_DIR=$(CURDIR)/libraries \
CP=cp enable_openieee=true
@echo
@echo ------------------------------------------------------------
@echo Installing with mcode backend
@echo ------------------------------------------------------------
if [ -n "$(WITH_MCODE)" ]; then \
$(MAKE) -C $(BUILDDIR)/mcode install.mcode.program install.vpi \
DESTDIR=../../debian/tmp; \
$(MAKE) -C $(BUILDDIR)/mcode install DESTDIR=../../debian/tmp; \
fi
@echo
@echo ------------------------------------------------------------
@echo Installing with llvm backend
@echo ------------------------------------------------------------
if [ -n "$(WITH_LLVM)" ]; then \
$(MAKE) -C $(BUILDDIR)/llvm install.llvm.program install.grt install.vpi \
DESTDIR=../../debian/tmp; \
$(MAKE) -C $(BUILDDIR)/llvm install DESTDIR=../../debian/tmp; \
fi
@echo
@echo ------------------------------------------------------------
......@@ -144,8 +140,26 @@ override_dh_auto_install:
if [ -n "$(WITH_GCC)" ]; then \
$(MAKE) -C $(BUILDDIR)/gcc/gccbuild install \
DESTDIR=$(CURDIR)/debian/tmp; \
$(MAKE) -C $(BUILDDIR)/gcc install.grt install.vpi \
DESTDIR=$(CURDIR)/debian/tmp; \
$(MAKE) -C $(BUILDDIR)/gcc install DESTDIR=$(CURDIR)/debian/tmp; \
mv debian/tmp/usr/lib/ghdl/gcc/bin/ghdl-gcc debian/tmp/usr/bin/ghdl-gcc; \
mv debian/tmp/usr/lib/ghdl/gcc/lib/ghdl/libbacktrace.a debian/tmp/usr/lib/ghdl/gcc/libbacktrace.a; \
fi
@echo
@echo ------------------------------------------------------------
@echo Moving parts to required locations
@echo ------------------------------------------------------------
if [ -n "$(WITH_MCODE)" ]; then \
$(RM) -r debian/tmp/usr/lib/ghdl/src; \
mv debian/tmp/usr/lib/ghdl/mcode/src debian/tmp/usr/lib/ghdl; \
ln -s ../src debian/tmp/usr/lib/ghdl/mcode/src; \
fi
if [ -n "$(WITH_LLVM)" ]; then \
$(RM) -r debian/tmp/usr/lib/ghdl/src; \
mv debian/tmp/usr/lib/ghdl/llvm/src debian/tmp/usr/lib/ghdl; \
ln -s ../src debian/tmp/usr/lib/ghdl/llvm/src; \
fi
if [ -n "$(WITH_GCC)" ]; then \
$(RM) -r debian/tmp/usr/lib/ghdl/src; \
mv debian/tmp/usr/lib/ghdl/gcc/src debian/tmp/usr/lib/ghdl; \
ln -s ../src debian/tmp/usr/lib/ghdl/gcc/src; \
fi
[library]
name = std
subdir = std
depends = __bootstrap
[compile]
[compile 87]
sources = std/textio.v87 std/textio_body.v87
[compile 93]
sources = std/textio.v93 std/textio_body.v93
[compile 08]
sources = std/textio.v08 std/textio_body.v08
std/env.vhdl std/env_body.vhdl
[library]
name = synopsys
work = ieee
copywork = yes
subdir = synopsys
depends = ieee
[compile]
[compile 87]
sources = synopsys/std_logic_arith.vhdl
synopsys/std_logic_unsigned.vhdl
synopsys/std_logic_signed.vhdl
synopsys/std_logic_misc.vhdl synopsys/std_logic_misc-body.vhdl
synopsys/std_logic_textio.vhdl
[compile 93]
sources = synopsys/std_logic_arith.vhdl
synopsys/std_logic_unsigned.vhdl
synopsys/std_logic_signed.vhdl
synopsys/std_logic_misc.vhdl synopsys/std_logic_misc-body.vhdl
synopsys/std_logic_textio.vhdl
[compile 08]
sources = synopsys/std_logic_arith.vhdl
synopsys/std_logic_unsigned.vhdl
synopsys/std_logic_signed.vhdl
synopsys/std_logic_misc.v08 synopsys/std_logic_misc-body.v08
#!/usr/bin/python3
#
# Compile all system wide installed VHDL libraries for GHDL
#
# Copyright (C) 2018 Andreas Bombe
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from pathlib import Path
from configparser import ConfigParser
from argparse import ArgumentParser
import os
import subprocess
verbose = False
exit_status = 0
backends = ('mcode', 'gcc', 'llvm')
standards = {
'87': {'name': 'VHDL-87', 'subdir': 'v87', 'flag': '--std=87'},
'93': {'name': 'VHDL-93', 'subdir': 'v93', 'flag': '--std=93'},
'08': {'name': 'VHDL-2008', 'subdir': 'v08', 'flag': '--std=08'},
}
librootdir = Path('/usr/lib/ghdl')
relsrcdir = Path('../../../src')
configdirs = (Path('/usr/lib/ghdl/config'),
Path('/usr/lib/ghdl/config-override'),
Path('/usr/local/lib/ghdl/config'))
def log(*msg):
'''log the msg (to be used instead of print())'''
print(*msg)
def logv(*msg):
'''call log() with the same args, but only if verbose is True'''
if verbose:
log(*msg)
def set_fail():
global exit_status
exit_status = 1
def backend_available(backend):
try:
result = subprocess.run(['ghdl-' + backend, '--version'], stdout=subprocess.DEVNULL)
except FileNotFoundError:
return False
return result.returncode == 0
def clean_dir(dirpath):
'''recursively unlink the contents of dirpath'''
#print('clean', dirpath)
if librootdir not in dirpath.resolve().parents:
raise RuntimeError('somehow moved out of libdir while cleaning directory')
for p in dirpath.iterdir():
if p.is_symlink():
# there aren't supposed to be symlinks in here, abort in case we
# somehow ended up in a directory we're not supposed to be in
raise RuntimeError('found unexpected symlink while cleaning directory')
elif p.is_dir():
clean_dir(p)
p.rmdir()
elif p.is_file():
p.unlink()
else:
# like is_symlink() above, but for special files
raise RuntimeError('found unexpected special file while cleaning directory')
def cleanup_libraries(backend):
logv('Cleaning up', backend, 'libraries')
libdir = librootdir / backend
for std in standards.values():
stddir = libdir / std['subdir']
if not stddir.is_dir():
# Something is wrong with the installation if these directories are
# not found, move forward but return error.
log('Directory not found, skipping:', stddir)
set_fail()
continue
clean_dir(stddir)
def find_configuration_files():
'''
Collect all files named *.ghdllib from the directories in configdirs.
Identically named files override those found in previously scanned
directories.
'''
configs = {}
for cp in configdirs:
for f in cp.glob('*.ghdllib'):
if f.is_file():
configs[f.stem] = f
return configs.values()
def read_configuration_values(conf, std):
lib = conf['library']
comp = conf['compile']
v = {}
v['name'] = lib['name']
v['work'] = lib.get('work', v['name'])
v['copywork'] = lib.getboolean('copywork', False)
v['subdir'] = lib.get('subdir', 'synopsys')
v['depends'] = lib.get('depends', 'ieee')
v['sources'] = comp.get('sources', '').split()
if 'compile ' + std in conf:
cstd = conf['compile ' + std]
v['sources'] += cstd.get('sources', '').split()
return v
def load_configuration():
specs = {x: [] for x in standards}
config_files = find_configuration_files()
for configpath in config_files:
config = ConfigParser()
config.read(configpath)
# basic check, if this passes the config is fundamentally valid and in
# the worst case just might not compile anything
if 'library' not in config or 'compile' not in config or 'name' not in config['library']:
log('ignoring', configpath)
continue
#print(config['library']['name'])
target_standards = config['library'].get('standards', '87 93 08').split()
for s in target_standards:
if s not in standards:
log('illegal value', s, 'for standard in', configpath)
set_fail()
continue
specs[s].append(read_configuration_values(config, s))
#print(specs)
return specs
def bootstrap_standard(backend, std):
if backend == 'mcode':
return
log(f'Bootstrap GHDL standard library for {std["name"]} ({backend})')
destdir = librootdir / backend / std['subdir'] / 'std'
destdir.mkdir()
os.chdir(destdir)
cmdline = ['ghdl-' + backend, '--bootstrap-standard', std['flag']]
logv(*cmdline)
result = subprocess.run(cmdline)
if result.returncode != 0:
set_fail()
def order_compilation(in_specs):
'''
Reorder compile specs by dependencies. The dependency __bootstrap is
special, it is the first "available" dependency.
'''
by_dep = {}
for s in in_specs:
dep = s['depends']
if dep not in by_dep:
by_dep[dep] = []
by_dep[dep].append(s)
out_specs = []
available = ['__bootstrap']
while len(available) > 0:
dep = available.pop(0)
for spec in by_dep.pop(dep, []):
available.append(spec['name'])
out_specs.append(spec)
for dep, specs in by_dep.items():
logv('not compiling due to missing library', dep + ':', *[x['name'] for x in specs])
return out_specs
def build_libraries(backend, specs, std):
log(f'Build GHDL libraries for {std["name"]} ({backend})')
destroot = librootdir / backend / std['subdir']
ghdl = 'ghdl-' + backend
common_args = ['-a', '-O', std['flag'], '-fexplicit', '-frelaxed-rules']
for spec in specs:
args = ['--work='+spec['work']]
if spec['name'] == 'std':
args.insert(0, '--bootstrap')
cmdline = [ghdl, *common_args, *args]
# create destdir if needed and change to it (compiled objects are left in
# current directory)
destdir = destroot / spec['subdir']
destdir.mkdir(exist_ok = True)
os.chdir(destdir)
# if requested, copy the library of the same name to the directory
if spec['copywork']:
copycmd = [ghdl, '--copy', std['flag'], '--work='+spec['work']]
logv(*copycmd)
result = subprocess.run(copycmd)
if result.returncode != 0:
set_fail()
for source in spec['sources']:
srcpath = Path(relsrcdir, source)
logv(*cmdline, srcpath)
result = subprocess.run([*cmdline, srcpath])
if result.returncode != 0:
set_fail()
def main():
global verbose
global backends
parser = ArgumentParser(description='Manage system-wide VHDL library compilation for GHDL')
parser.add_argument('--backend', choices=['mcode', 'gcc', 'llvm'],
help='act only on the compiled libraries for the specified GHDL backend')
parser.add_argument('--cleanup', action='store_true',
help='only remove compiled libraries, don\'t recompile')
parser.add_argument('-v', '--verbose', action='store_true',
help='print more information')
args = parser.parse_args()
cleanup_only = args.cleanup
verbose = args.verbose
if args.backend is not None:
backends = (args.backend,)
if not cleanup_only:
compile_specs = load_configuration()
for backend in backends:
if not backend_available(backend):
logv(f'Skipping {backend} backend, not available')
continue
cleanup_libraries(backend)
if not cleanup_only:
for std in standards:
bootstrap_standard(backend, standards[std])
seq_specs = order_compilation(compile_specs[std])
build_libraries(backend, seq_specs, standards[std])
if __name__ == '__main__':
main()
exit(exit_status)
.\" update-ghdl-libraries.8
.\"
.\" Compile all system wide installed VHDL libraries for GHDL
.\"
.\" Copyright (C) 2018 Andreas Bombe
.\"
.\" This program is free software; you can redistribute it and/or modify
.\" it under the terms of the GNU General Public License as published by
.\" the Free Software Foundation; either version 2 of the License, or
.\" (at your option) any later version.
.\"
.\" This program is distributed in the hope that it will be useful,
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
.\" GNU General Public License for more details.
.\"
.\" You should have received a copy of the GNU General Public License along
.\" with this program; if not, write to the Free Software Foundation, Inc.,
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
.\"
.\" ----------------------------------------------------------------------------
.TH UPDATE-GHDL-LIBRARIES 8 2018\-01\-07 "ghdl"
.SH NAME
update\-ghdl\-libraries \- compile all system wide installed VHDL libraries for GHDL
.\" ----------------------------------------------------------------------------
.SH SYNOPSIS
\fBupdate\-ghdl\-libraries\fR [\fIOPTIONS\fR]
.\" ----------------------------------------------------------------------------
.SH DESCRIPTION
\fBupdate\-ghdl\-libraries\fR is a tool to manage compilation of system wide
installed VHDL libraries for the VHDL simulator GHDL.
The principle of operation is to install library source files and an
accompanying configuration files into specific directories
\fBupdate\-ghdl\-libraries\fR will read from and compile the library sources
when invoked.
.PP
The tool can be manually invoked by the system administrator after creating or
updating local library installations.