Skip to content
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