Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sage -package dependencies #37350

Merged
merged 9 commits into from
Feb 25, 2024
34 changes: 9 additions & 25 deletions build/bin/sage-spkg-info
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,21 @@ if [ -n "$OUTPUT_RST" ]; then
issue () { echo ":issue:\`$1\`"; }
code () { echo "\`\`$*\`\`"; }
tab () { echo ".. tab:: $1"; }
FORMAT=rst
else
ref () { echo "$1"; }
spkg () { echo "$1"; }
issue () { echo "https://github.com/sagemath/sage/issues/$1"; }
code () { echo "$1"; }
tab () { echo "$1:"; }
FORMAT=plain
fi
PKG_SCRIPTS="$SAGE_ROOT/build/pkgs/$PKG_BASE"
if ! props=$(sage-package properties --format=shell $PKG_BASE 2> /dev/null); then
echo >&2 "sage-spkg-info: unknown package $PKG_BASE"
exit 1
fi
eval "$props"
eval PKG_SCRIPTS=\$path_$PKG_BASE
for ext in rst txt; do
SPKG_FILE="$PKG_SCRIPTS/SPKG.$ext"
if [ -f "$SPKG_FILE" ]; then
Expand All @@ -44,30 +51,7 @@ echo
echo "Dependencies"
echo "------------"
echo
dep=
for dep_file in dependencies dependencies_order_only; do
if [ -r "$PKG_SCRIPTS/$dep_file" ] ; then
for dep in $(sed 's/^ *//; s/ *#.*//; q' "$PKG_SCRIPTS/$dep_file"); do
case "$dep" in
# Do not use order-only syntax, too much information
\|) ;;
# Suppress dependencies on source file of the form $(SAGE_ROOT)/..., $(SAGE_SRC)/...
\$\(SAGE_*) ;;
# Suppress FORCE
FORCE) ;;
# Dependencies like $(BLAS)
\$\(*) echo "- $dep";;
# Looks like a package
*) if [ -r "$SAGE_ROOT/build/pkgs/$dep/SPKG.rst" ]; then
# This RST label is set in src/doc/bootstrap
echo "- $(spkg $dep)"
else
echo "- $dep"
fi;;
esac
done
fi
done
sage-package dependencies --format=$FORMAT $PKG_BASE
echo
echo "Version Information"
echo "-------------------"
Expand Down
2 changes: 1 addition & 1 deletion build/pkgs/giac/dependencies
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
readline libpng $(MP_LIBRARY) mpfr mpfi ntl gsl pari glpk curl cliquer ecm $(findstring libnauty,$(OPTIONAL_INSTALLED_PACKAGES))
readline libpng $(MP_LIBRARY) mpfr mpfi ntl gsl pari glpk curl cliquer ecm

----------
All lines of this file are ignored except the first.
1 change: 1 addition & 0 deletions build/pkgs/giac/dependencies_optional
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
libnauty
78 changes: 76 additions & 2 deletions build/sage_bootstrap/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,9 @@ def properties(self, *package_classes, **kwds):
pc = PackageClass(*package_classes)
for package_name in pc.names:
package = Package(package_name)
if format == 'plain':
print("{0}:".format(package_name))
if len(pc.names) > 1:
if format == 'plain':
print("{0}:".format(package_name))
for p in props:
value = getattr(package, p)
if value is None:
Expand All @@ -108,6 +109,79 @@ def properties(self, *package_classes, **kwds):
else:
print("{0}_{1}='{2}'".format(p, package_name, value))

def dependencies(self, *package_classes, **kwds):
"""
Find the dependencies given package names

$ sage --package dependencies maxima --runtime --order-only --format=shell
order_only_deps_maxima='info'
runtime_deps_maxima='ecl'
"""
types = kwds.pop('types', None)
format = kwds.pop('format', 'plain')
log.debug('Looking up dependencies')
pc = PackageClass(*package_classes)
if format in ['plain', 'rst']:
if types is None:
typesets = [['order_only', 'runtime']]
else:
typesets = [[t] for t in types]
elif format == 'shell':
if types is None:
types = ['order_only', 'optional', 'runtime', 'check']
typesets = [[t] for t in types]
else:
raise ValueError('format must be one of "plain", "rst", and "shell"')

for package_name in pc.names:
package = Package(package_name)
if len(pc.names) > 1:
if format == 'plain':
print("{0}:".format(package_name))
indent1 = " "
elif format == 'rst':
print("\n{0}\n{1}\n".format(package_name, "~" * len(package_name)))
indent1 = ""
else:
indent1 = ""

for typeset in typesets:
if len(typesets) > 1:
if format == 'plain':
print(indent1 + "{0}: ".format('/'.join(typeset)))
indent2 = indent1 + " "
elif format == 'rst':
print("\n" + indent1 + ".. tab:: {0}\n".format('/'.join(typeset)))
indent2 = indent1 + " "
else:
indent2 = indent1

deps = []
for t in typeset:
deps.extend(getattr(package, 'dependencies_' + t))
deps = sorted(set(deps))

if format in ['plain', 'rst']:
for dep in deps:
if '/' in dep:
# Suppress dependencies on source files, e.g. of the form $(SAGE_ROOT)/..., $(SAGE_SRC)/...
continue
if dep == 'FORCE':
# Suppress FORCE
continue
if dep.startswith('$('):
# Dependencies like $(BLAS)
print(indent2 + "- {0}".format(dep))
elif format == 'rst' and Package(dep).has_file('SPKG.rst'):
# This RST label is set in src/doc/bootstrap
print(indent2 + "- :ref:`spkg_{0}`".format(dep))
else:
print(indent2 + "- {0}".format(dep))
elif format == 'shell':
# We single-quote the values because dependencies
# may contain Makefile variable substitutions
print("{0}_deps_{1}='{2}'".format(t, package_name, ' '.join(deps)))

def name(self, tarball_filename):
"""
Find the package name given a tarball filename
Expand Down
68 changes: 68 additions & 0 deletions build/sage_bootstrap/cmdline.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,36 @@
"""


epilog_dependencies = \
"""
Print the list of packages that are dependencies of given package.
By default, list a summary of the build, order-only, and runtime
dependencies.

EXAMPLE:

$ sage --package dependencies maxima openblas
maxima:
- ecl
- info
openblas:
- gfortran
$ sage --package dependencies maxima --runtime
- ecl

$ sage --package dependencies maxima openblas --runtime --order-only
maxima:
order_only:
- info
runtime:
- ecl
openblas:
order_only:
runtime:
- gfortran
"""


epilog_name = \
"""
Find the package name given a tarball filename
Expand Down Expand Up @@ -286,6 +316,31 @@ def make_parser():
'--format', type=str, default='plain',
help='output format (one of plain and shell; default: plain)')

parser_dependencies = subparsers.add_parser(
'dependencies', epilog=epilog_dependencies,
formatter_class=argparse.RawDescriptionHelpFormatter,
help='Print the list of packages that are dependencies of given packages')
parser_dependencies.add_argument(
'package_class', metavar='[package_name|:package_type:]',
type=str, nargs='+',
help=('package name or designator for all packages of a given type '
'(one of :all:, :standard:, :optional:, and :experimental:)'))
parser_dependencies.add_argument(
'--order-only', action='store_true',
help='list the order-only build dependencies')
parser_dependencies.add_argument(
'--optional', action='store_true',
help='list the optional build dependencies')
parser_dependencies.add_argument(
'--runtime', action='store_true',
help='list the runtime dependencies')
parser_dependencies.add_argument(
'--check', action='store_true',
help='list the check dependencies')
parser_dependencies.add_argument(
'--format', type=str, default='plain',
help='output format (one of plain, rst, and shell; default: plain)')

parser_name = subparsers.add_parser(
'name', epilog=epilog_name,
formatter_class=argparse.RawDescriptionHelpFormatter,
Expand Down Expand Up @@ -435,6 +490,19 @@ def run():
exclude_dependencies=args.exclude_dependencies)
elif args.subcommand == 'properties':
app.properties(*args.package_class, format=args.format)
elif args.subcommand == 'dependencies':
types = []
if args.order_only:
types.append('order_only')
if args.optional:
types.append('optional')
if args.runtime:
types.append('runtime')
if args.check:
types.append('check')
if not types:
types = None
app.dependencies(*args.package_class, types=types, format=args.format)
elif args.subcommand == 'name':
app.name(args.tarball_filename)
elif args.subcommand == 'tarball':
Expand Down
28 changes: 25 additions & 3 deletions build/sage_bootstrap/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,23 @@ def dependencies_order_only(self):
"""
return self.__dependencies.partition('|')[2].strip().split() + self.__dependencies_order_only.strip().split()

@property
def dependencies_optional(self):
"""
Return a list of strings, the package names of the optional build dependencies
"""
return self.__dependencies_optional.strip().split()

@property
def dependencies_runtime(self):
"""
Return a list of strings, the package names of the runtime dependencies
"""
# after a '|', we have order-only build dependencies
return self.__dependencies.partition('|')[0].strip().split()

dependencies = dependencies_runtime

@property
def dependencies_check(self):
"""
Expand Down Expand Up @@ -503,17 +520,22 @@ def _init_install_requires(self):
def _init_dependencies(self):
try:
with open(os.path.join(self.path, 'dependencies')) as f:
self.__dependencies = f.readline().strip()
self.__dependencies = f.readline().partition('#')[0].strip()
except IOError:
self.__dependencies = ''
try:
with open(os.path.join(self.path, 'dependencies_check')) as f:
self.__dependencies_check = f.readline().strip()
self.__dependencies_check = f.readline().partition('#')[0].strip()
except IOError:
self.__dependencies_check = ''
try:
with open(os.path.join(self.path, 'dependencies_optional')) as f:
self.__dependencies_optional = f.readline().partition('#')[0].strip()
except IOError:
self.__dependencies_optional = ''
try:
with open(os.path.join(self.path, 'dependencies_order_only')) as f:
self.__dependencies_order_only = f.readline()
self.__dependencies_order_only = f.readline().partition('#')[0].strip()
except IOError:
self.__dependencies_order_only = ''

Expand Down
Loading