From ad658e701fa0b128d49c45a96e4278ad399bbe32 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 4 Jan 2024 14:48:36 -0800 Subject: [PATCH 01/30] src/bin/sage-cython: Repurpose as PEP 420 fixer, ship with sagemath-environment --- pkgs/sagemath-environment/pyproject.toml.m4 | 3 ++ src/bin/sage-cython | 49 ++++++++------------- 2 files changed, 21 insertions(+), 31 deletions(-) diff --git a/pkgs/sagemath-environment/pyproject.toml.m4 b/pkgs/sagemath-environment/pyproject.toml.m4 index 44ddd190f99..c5488bc864d 100644 --- a/pkgs/sagemath-environment/pyproject.toml.m4 +++ b/pkgs/sagemath-environment/pyproject.toml.m4 @@ -50,6 +50,9 @@ script-files = [ "bin/sage-version.sh", # Auxiliary script for invoking Python in the Sage environment "bin/sage-python", + # The following is freshly un-deprecated as a temporary workaround + # for defects in Cython 3.0.x support for PEP 420 implicit namespace packages + "bin/sage-cython", # Not included: # - bin/sage-env-config -- installed by sage_conf # - bin/sage-env-config.in -- not to be installed diff --git a/src/bin/sage-cython b/src/bin/sage-cython index a52a729dd02..a189e44ce1d 100755 --- a/src/bin/sage-cython +++ b/src/bin/sage-cython @@ -1,39 +1,26 @@ -#!/usr/bin/env sage-python +#!/usr/bin/env python -# This script is a deprecated wrapper around the "cython" program. -# It is deprecated since Issue #27041 (Sage 8.7) because one should +# This script is a wrapper around the "cython" program. +# It was deprecated in Issue #27041 (Sage 8.7) because one should # simply use "cython" directly. We display deprecation messages whenever # "sage-cython" does something different from plain "cython". # # A stronger deprecation warning was added in #29923 (Sage 9.2). +# +# In Sage 10.3, the deprecated functionality is removed permanently. +# However, the script is un-deprecated and re-purposed as a temporary workaround +# for defects in Cython 3.0.x support for PEP 420 implicit namespace packages, +# see https://github.com/sagemath/sage/pull/36228 +# +# This script can be used as a replacement for "cython". +# For example, to have meson use it, set the environment variable +# CYTHON to sage-cython./ +# https://github.com/mesonbuild/meson/blob/e4bbc630b67ef97ad842badd00855e64cff12e13/mesonbuild/envconfig.py#L91 -import os -import sys -args = sys.argv[1:] - -sys.stderr.write("WARNING: the script sage-cython is deprecated; use cython instead.\n") - -from sage.env import SAGE_SRC - -# args can have length 0, in case we're printing a usage message (see trac 12207) -pyx_file = os.path.abspath(args[-1]) if len(args) else None -include_sage_flags = False - -if pyx_file and pyx_file.startswith(SAGE_SRC): - sys.stderr.write("WARNING: in the future, sage --cython will not add special flags for files in Sage sources.\n") - include_sage_flags = True - -if '-sage' in args: - sys.stderr.write("WARNING: sage --cython -sage is deprecated.\n") - include_sage_flags = True - args.remove('-sage') -elif '-no-sage' in args: - sys.stderr.write("WARNING: sage --cython -no-sage is deprecated, remove the -no-sage flag.\n") - include_sage_flags = False - args.remove('-no-sage') +from sage.misc.package_dir import cython_namespace_package_support -if include_sage_flags: - args = ['--embed-positions', '-I%s' % SAGE_SRC] + args +# console scripts declared in https://github.com/cython/cython/blob/master/setup.py#L68 +from Cython.Compiler.Main import setuptools_main -args.insert(0, 'sage-cython') -os.execlp('cython', *args) +with cython_namespace_package_support(): + setuptools_main() From 39482005fe9e819017584567364162e9e2eb11b3 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sun, 31 Dec 2023 10:32:58 -0800 Subject: [PATCH 02/30] Add generate-meson.py From PR 'Compile everything with meson' (https://github.com/sagemath/sage/pull/36524 at 46bc6b4279c47c3f12c7da29f309b053a5cdb17c (2023-12-31) --- generate-meson.py | 198 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 generate-meson.py diff --git a/generate-meson.py b/generate-meson.py new file mode 100644 index 00000000000..1bcb7fc3871 --- /dev/null +++ b/generate-meson.py @@ -0,0 +1,198 @@ +# Small script that generates a meson.build file in the given folder. +# The generated build file contains all python files as `install_sources` and all cython files as `extension_module` + +import argparse +import sys +from pathlib import Path +from types import SimpleNamespace + +parser = argparse.ArgumentParser(description='Generate meson.build file for a given folder.') +parser.add_argument('folder', type=str, nargs='?', default='.', + help='folder for which the meson.build file will be generated') +parser.add_argument('--dry-run', '-n', action='store_true', + help='do not write any files, just print the output') +parser.add_argument('--force', '-f', action='store_true', + help='overwrite existing meson.build file') + +args = parser.parse_args() + +def run(folder: Path): + dry_run = args.dry_run + force = args.force + + if not folder.is_dir(): + print(f'Error: {folder} is not a directory') + return + folder_rel_to_src = folder.relative_to('src') + + python_files = sorted(list(folder.glob('*.py')) + list(folder.glob('*.pxd')) + list(folder.glob('*.h'))) + cython_files = sorted(list(folder.glob('*.pyx'))) + + + if not python_files and not cython_files: + print(f'Error: {folder} does not contain any python or cython files') + return + + def get_metadata(path: Path): + with open(path, 'r') as file: + metadata = SimpleNamespace() + metadata.path = path + metadata.libraries = [] + for line in file: + if line.startswith('# distutils: libraries ='): + libraries = line.split('libraries =')[1].strip().split() + libraries = [ + library + .replace('ARB_LIBRARY', 'arb') + .replace('NTL_LIBRARIES', 'ntl') + .replace('SINGULAR_LIBRARIES', 'singular') + .replace('LINBOX_LIBRARIES', 'linbox') + .replace('FFLASFFPACK_LIBRARIES', 'fflas') + .replace('GSL_LIBRARIES', 'gsl') + .replace('M4RI_LIBRARIES', 'm4ri') + .replace('GDLIB_LIBRARIES', 'gd') + .replace('LIBPNG_LIBRARIES', 'png') + .replace('CBLAS_LIBRARIES', 'cblas') + .replace('ZLIB_LIBRARIES', 'zlib') + .replace('Lfunction', 'lfunction') + for library in libraries] + try: + libraries.remove('CYGWIN_SQLITE3_LIBS') + except ValueError: + pass + metadata.libraries += libraries + + metadata.inc_dirs = [] + c_file = path.with_suffix('.c') + cpp_file = path.with_suffix('.cpp') + if cpp_file.exists(): + metadata.is_cpp = True + c_file = cpp_file + else: + metadata.is_cpp = False + if c_file.exists(): + metadata.not_yet_on_conda = False + with open(c_file, 'r') as c_file: + contents = c_file.read() + known_inc_dirs = { + 'sage/cpython/': 'inc_cpython', + 'sage/rings': 'inc_rings', + 'sage/rings/finite_rings': 'inc_rings_finite', + 'sage/libs/flint': 'inc_flint', + 'sage/libs/gsl': 'inc_gsl', + 'sage/libs/ntl': 'inc_ntl', + 'sage/libs/arb': 'inc_arb', + 'sage/data_structures': 'inc_data_structures', + 'sage/ext/': 'inc_ext', + 'numpy/core/include/': 'inc_numpy', + 'sage/symbolic/ginac/': 'inc_ginac', + 'sage/symbolic/pynac_wrap.h': 'inc_pynac', + 'sage/groups/perm_gps/partn_ref2/': 'inc_partn_ref2', + 'sage/ext/interpreters/': 'inc_interpreters', + } + for known_inc_dir in known_inc_dirs: + if known_inc_dir in contents: + metadata.inc_dirs.append(known_inc_dirs[known_inc_dir]) + known_libs = { + 'cypari2/': 'cypari2', + 'cysignals/': 'cysignals', + '/gmp.h': 'gmp', + '/iml.h': 'iml', + '/m4ri/': 'm4ri', + '/pari/': 'pari', + '/flint/': 'flint', + '/fflas-ffpack/': 'fflas', + '/givaro/': 'givaro', + '/gmp++/': 'gmpxx', + '/linbox/': 'linbox', + '/gsl/': 'gsl', + 'mpfr.h': 'mpfr', + 'sage/symbolic/ginac/': 'ginac', + 'arb.h': 'arb', + 'mpfi.h': 'mpfi', + 'mpc.h': 'mpc', + 'gmpy2/': 'gmpy2', + } + for known_lib in known_libs: + if known_lib in contents: + metadata.libraries.append(known_libs[known_lib]) + else: + metadata.not_yet_on_conda = metadata.is_cpp is False + + return metadata + + cython_files = [get_metadata(file) for file in cython_files] + cython_c_files = [file for file in cython_files if not file.is_cpp] + cython_cpp_files = [file for file in cython_files if file.is_cpp] + all_libraries = sorted(set(library for file in cython_files for library in file.libraries) | {'gmp'}) + all_inc_dirs = sorted(set(inc_dir for file in cython_files for inc_dir in file.inc_dirs)) + subdirs = sorted(list(folder.glob('*/'))) + + meson_build_path = folder / 'meson.build' + if not dry_run and not force and meson_build_path.exists(): + print(f'Error: {meson_build_path} already exists, use --force to overwrite') + return + + with open(meson_build_path, 'w') if not dry_run else sys.stdout as meson_build: + meson_build.write('py.install_sources(\n') + for file in python_files: + meson_build.write(f" '{file.name}',\n") + meson_build.write(f" subdir: '{folder_rel_to_src}',\n") + meson_build.write(')\n') + + if cython_c_files: + meson_build.write('\n') + meson_build.write('extension_data = {\n') + for file in cython_c_files: + if file.not_yet_on_conda: + meson_build.write(f" # '{file.path.stem}': files('{file.path.name}'), # not yet on conda\n") + else: + meson_build.write(f" '{file.path.stem}': files('{file.path.name}'),\n") + meson_build.write('}\n\n') + + meson_build.write('foreach name, pyx : extension_data\n') + meson_build.write(" py.extension_module(name,\n") + meson_build.write(" sources: pyx,\n") + meson_build.write(f" subdir: '{folder_rel_to_src}',\n") + meson_build.write(' install: true,\n') + meson_build.write(f" include_directories: [{', '.join(all_inc_dirs)}],\n") + meson_build.write(f" dependencies: [py_dep{', ' if all_libraries else ''}{', '.join(all_libraries)}],\n") + meson_build.write(' )\n') + meson_build.write('endforeach\n') + + if cython_cpp_files: + meson_build.write('\n') + meson_build.write('extension_data_cpp = {\n') + for file in cython_cpp_files: + if file.not_yet_on_conda: + meson_build.write(f" # '{file.path.stem}': files('{file.path.name}'), # not yet on conda\n") + else: + meson_build.write(f" '{file.path.stem}': files('{file.path.name}'),\n") + meson_build.write('}\n\n') + + meson_build.write('foreach name, pyx : extension_data_cpp\n') + meson_build.write(" py.extension_module(name,\n") + meson_build.write(" sources: pyx,\n") + meson_build.write(f" subdir: '{folder_rel_to_src}',\n") + meson_build.write(' install: true,\n') + meson_build.write(' override_options : [\'cython_language=cpp\'],\n') + meson_build.write(f" include_directories: [{', '.join(all_inc_dirs)}],\n") + meson_build.write(f" dependencies: [py_dep{', ' if all_libraries else ''}{', '.join(all_libraries)}],\n") + meson_build.write(' )\n') + meson_build.write('endforeach\n') + + meson_build.write('\n') + for subdir in subdirs: + if subdir.name.startswith('_') or subdir.name.startswith('.'): + continue + if not list(subdir.glob('*.py*')): + continue + + if not list(subdir.glob('*.pyx')): + meson_build.write(f"install_subdir('{subdir.name}', install_dir: sage_install_dir / '{folder_rel_to_src.relative_to('sage')}')\n") + else: + meson_build.write(f"subdir('{subdir.name}')\n") + run(subdir) + +folder = Path(args.folder) +run(folder) From 903eed0bbd7df97efae1c2ca6d7ed7ce91fbd9c8 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 4 Jan 2024 12:14:51 -0800 Subject: [PATCH 03/30] Move generate-meson.py to src/sage_setup/autogen/meson/__init__.py --- generate-meson.py => src/sage_setup/autogen/meson/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename generate-meson.py => src/sage_setup/autogen/meson/__init__.py (100%) diff --git a/generate-meson.py b/src/sage_setup/autogen/meson/__init__.py similarity index 100% rename from generate-meson.py rename to src/sage_setup/autogen/meson/__init__.py From 7059c98ab5ff67d5d9533edd0cc2d1925a8dfafc Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 4 Jan 2024 12:54:21 -0800 Subject: [PATCH 04/30] pkgs/sage-setup/pyproject.toml: Add script sage-generate-meson --- pkgs/sage-setup/pyproject.toml | 4 +++ src/sage_setup/autogen/meson/__init__.py | 33 +++++++++++++----------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/pkgs/sage-setup/pyproject.toml b/pkgs/sage-setup/pyproject.toml index 1499fe4c9ba..a9062aa38e9 100644 --- a/pkgs/sage-setup/pyproject.toml +++ b/pkgs/sage-setup/pyproject.toml @@ -33,12 +33,16 @@ content-type = "text/x-rst" [project.optional-dependencies] autogen = ["jinja2"] +[project.scripts] +sage-generate-meson = "sage_setup.autogen.meson:generate_meson" + [tool.setuptools] packages = [ "sage_setup", "sage_setup.autogen", "sage_setup.autogen.interpreters", "sage_setup.autogen.interpreters.specs", + "sage_setup.autogen.meson", "sage_setup.command", ] include-package-data = false diff --git a/src/sage_setup/autogen/meson/__init__.py b/src/sage_setup/autogen/meson/__init__.py index 1bcb7fc3871..666d9493bc9 100644 --- a/src/sage_setup/autogen/meson/__init__.py +++ b/src/sage_setup/autogen/meson/__init__.py @@ -1,24 +1,12 @@ # Small script that generates a meson.build file in the given folder. # The generated build file contains all python files as `install_sources` and all cython files as `extension_module` -import argparse import sys from pathlib import Path from types import SimpleNamespace -parser = argparse.ArgumentParser(description='Generate meson.build file for a given folder.') -parser.add_argument('folder', type=str, nargs='?', default='.', - help='folder for which the meson.build file will be generated') -parser.add_argument('--dry-run', '-n', action='store_true', - help='do not write any files, just print the output') -parser.add_argument('--force', '-f', action='store_true', - help='overwrite existing meson.build file') -args = parser.parse_args() - -def run(folder: Path): - dry_run = args.dry_run - force = args.force +def run(folder: Path, dry_run=False, force=False): if not folder.is_dir(): print(f'Error: {folder} is not a directory') @@ -194,5 +182,20 @@ def get_metadata(path: Path): meson_build.write(f"subdir('{subdir.name}')\n") run(subdir) -folder = Path(args.folder) -run(folder) + +def generate_meson(): + import argparse + + parser = argparse.ArgumentParser(description='Generate meson.build file for a given folder.') + parser.add_argument('folder', type=str, nargs='?', default='.', + help='folder for which the meson.build file will be generated') + parser.add_argument('--dry-run', '-n', action='store_true', + help='do not write any files, just print the output') + parser.add_argument('--force', '-f', action='store_true', + help='overwrite existing meson.build file') + + args = parser.parse_args() + + folder = Path(args.folder) + run(folder, dry_run=args.dry_run, force=args.force) + return 0 From fbb080bebfc2a7e70822c57d01b29a4172cfcd8b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 4 Jan 2024 13:24:03 -0800 Subject: [PATCH 05/30] autopep8 -i src/sage_setup/autogen/meson/__init__.py --- src/sage_setup/autogen/meson/__init__.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/sage_setup/autogen/meson/__init__.py b/src/sage_setup/autogen/meson/__init__.py index 666d9493bc9..f0418f2db7b 100644 --- a/src/sage_setup/autogen/meson/__init__.py +++ b/src/sage_setup/autogen/meson/__init__.py @@ -16,7 +16,6 @@ def run(folder: Path, dry_run=False, force=False): python_files = sorted(list(folder.glob('*.py')) + list(folder.glob('*.pxd')) + list(folder.glob('*.h'))) cython_files = sorted(list(folder.glob('*.pyx'))) - if not python_files and not cython_files: print(f'Error: {folder} does not contain any python or cython files') return @@ -43,7 +42,7 @@ def get_metadata(path: Path): .replace('CBLAS_LIBRARIES', 'cblas') .replace('ZLIB_LIBRARIES', 'zlib') .replace('Lfunction', 'lfunction') - for library in libraries] + for library in libraries] try: libraries.remove('CYGWIN_SQLITE3_LIBS') except ValueError: @@ -147,7 +146,7 @@ def get_metadata(path: Path): meson_build.write(f" dependencies: [py_dep{', ' if all_libraries else ''}{', '.join(all_libraries)}],\n") meson_build.write(' )\n') meson_build.write('endforeach\n') - + if cython_cpp_files: meson_build.write('\n') meson_build.write('extension_data_cpp = {\n') @@ -175,7 +174,7 @@ def get_metadata(path: Path): continue if not list(subdir.glob('*.py*')): continue - + if not list(subdir.glob('*.pyx')): meson_build.write(f"install_subdir('{subdir.name}', install_dir: sage_install_dir / '{folder_rel_to_src.relative_to('sage')}')\n") else: From de52fc115c125ac29c5b2d91089e8284bf663dee Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 4 Jan 2024 21:23:59 -0800 Subject: [PATCH 06/30] sage-generate-meson: Conditionalize by distribution variables in meson.build --- src/sage_setup/autogen/meson/__init__.py | 136 +++++++++++++++-------- 1 file changed, 88 insertions(+), 48 deletions(-) diff --git a/src/sage_setup/autogen/meson/__init__.py b/src/sage_setup/autogen/meson/__init__.py index f0418f2db7b..52d9d7ad252 100644 --- a/src/sage_setup/autogen/meson/__init__.py +++ b/src/sage_setup/autogen/meson/__init__.py @@ -2,9 +2,13 @@ # The generated build file contains all python files as `install_sources` and all cython files as `extension_module` import sys + +from collections import defaultdict from pathlib import Path from types import SimpleNamespace +from sage.misc.package_dir import read_distribution + def run(folder: Path, dry_run=False, force=False): @@ -24,9 +28,16 @@ def get_metadata(path: Path): with open(path, 'r') as file: metadata = SimpleNamespace() metadata.path = path + metadata.distribution = read_distribution(path) + + if path.suffix not in [".pxd", ".pxi", ".pyx"]: + return metadata + metadata.libraries = [] for line in file: - if line.startswith('# distutils: libraries ='): + if not line: + pass + elif line.startswith('# distutils: libraries ='): libraries = line.split('libraries =')[1].strip().split() libraries = [ library @@ -48,6 +59,10 @@ def get_metadata(path: Path): except ValueError: pass metadata.libraries += libraries + elif line.startswith('#'): + pass + else: + break metadata.inc_dirs = [] c_file = path.with_suffix('.c') @@ -108,6 +123,7 @@ def get_metadata(path: Path): return metadata + python_files = [get_metadata(file) for file in python_files] cython_files = [get_metadata(file) for file in cython_files] cython_c_files = [file for file in cython_files if not file.is_cpp] cython_cpp_files = [file for file in cython_files if file.is_cpp] @@ -120,55 +136,76 @@ def get_metadata(path: Path): print(f'Error: {meson_build_path} already exists, use --force to overwrite') return + print(f'Writing {meson_build_path}', file=sys.stderr) with open(meson_build_path, 'w') if not dry_run else sys.stdout as meson_build: - meson_build.write('py.install_sources(\n') - for file in python_files: - meson_build.write(f" '{file.name}',\n") - meson_build.write(f" subdir: '{folder_rel_to_src}',\n") - meson_build.write(')\n') - if cython_c_files: + by_distribution = defaultdict(lambda: SimpleNamespace(python_files=[], + cython_c_files=[], + cython_cpp_files=[])) + for python_file in python_files: + by_distribution[python_file.distribution].python_files.append(python_file) + for cython_c_file in cython_c_files: + by_distribution[cython_c_file.distribution].cython_c_files.append(cython_c_file) + for cython_cpp_file in cython_cpp_files: + by_distribution[cython_cpp_file.distribution].cython_cpp_files.append(cython_cpp_file) + + for distribution, files in by_distribution.items(): + + distribution_variable = 'distribution_' + distribution.replace('-', '_') + meson_build.write(f"if get_variable('{distribution_variable}', false)\n") + + if files.python_files: + meson_build.write('py.install_sources(\n') + for file in files.python_files: + meson_build.write(f" '{file.path.name}',\n") + meson_build.write(f" subdir: '{folder_rel_to_src}',\n") + meson_build.write(')\n') + + if files.cython_c_files: + meson_build.write('\n') + meson_build.write('extension_data = {\n') + for file in files.cython_c_files: + if file.not_yet_on_conda: + meson_build.write(f" # '{file.path.stem}': files('{file.path.name}'), # not yet on conda\n") + else: + meson_build.write(f" '{file.path.stem}': files('{file.path.name}'),\n") + meson_build.write('}\n\n') + + meson_build.write('foreach name, pyx : extension_data\n') + meson_build.write(" py.extension_module(name,\n") + meson_build.write(" sources: pyx,\n") + meson_build.write(f" subdir: '{folder_rel_to_src}',\n") + meson_build.write(' install: true,\n') + meson_build.write(f" include_directories: [{', '.join(all_inc_dirs)}],\n") + meson_build.write(f" dependencies: [py_dep{', ' if all_libraries else ''}{', '.join(all_libraries)}],\n") + meson_build.write(' )\n') + meson_build.write('endforeach\n') + + if files.cython_cpp_files: + meson_build.write('\n') + meson_build.write('extension_data_cpp = {\n') + for file in files.cython_cpp_files: + if file.not_yet_on_conda: + meson_build.write(f" # '{file.path.stem}': files('{file.path.name}'), # not yet on conda\n") + else: + meson_build.write(f" '{file.path.stem}': files('{file.path.name}'),\n") + meson_build.write('}\n\n') + + meson_build.write('foreach name, pyx : extension_data_cpp\n') + meson_build.write(" py.extension_module(name,\n") + meson_build.write(" sources: pyx,\n") + meson_build.write(f" subdir: '{folder_rel_to_src}',\n") + meson_build.write(' install: true,\n') + meson_build.write(' override_options : [\'cython_language=cpp\'],\n') + meson_build.write(f" include_directories: [{', '.join(all_inc_dirs)}],\n") + meson_build.write(f" dependencies: [py_dep{', ' if all_libraries else ''}{', '.join(all_libraries)}],\n") + meson_build.write(' )\n') + meson_build.write('endforeach\n') + + meson_build.write('endif\n') meson_build.write('\n') - meson_build.write('extension_data = {\n') - for file in cython_c_files: - if file.not_yet_on_conda: - meson_build.write(f" # '{file.path.stem}': files('{file.path.name}'), # not yet on conda\n") - else: - meson_build.write(f" '{file.path.stem}': files('{file.path.name}'),\n") - meson_build.write('}\n\n') - - meson_build.write('foreach name, pyx : extension_data\n') - meson_build.write(" py.extension_module(name,\n") - meson_build.write(" sources: pyx,\n") - meson_build.write(f" subdir: '{folder_rel_to_src}',\n") - meson_build.write(' install: true,\n') - meson_build.write(f" include_directories: [{', '.join(all_inc_dirs)}],\n") - meson_build.write(f" dependencies: [py_dep{', ' if all_libraries else ''}{', '.join(all_libraries)}],\n") - meson_build.write(' )\n') - meson_build.write('endforeach\n') - - if cython_cpp_files: - meson_build.write('\n') - meson_build.write('extension_data_cpp = {\n') - for file in cython_cpp_files: - if file.not_yet_on_conda: - meson_build.write(f" # '{file.path.stem}': files('{file.path.name}'), # not yet on conda\n") - else: - meson_build.write(f" '{file.path.stem}': files('{file.path.name}'),\n") - meson_build.write('}\n\n') - - meson_build.write('foreach name, pyx : extension_data_cpp\n') - meson_build.write(" py.extension_module(name,\n") - meson_build.write(" sources: pyx,\n") - meson_build.write(f" subdir: '{folder_rel_to_src}',\n") - meson_build.write(' install: true,\n') - meson_build.write(' override_options : [\'cython_language=cpp\'],\n') - meson_build.write(f" include_directories: [{', '.join(all_inc_dirs)}],\n") - meson_build.write(f" dependencies: [py_dep{', ' if all_libraries else ''}{', '.join(all_libraries)}],\n") - meson_build.write(' )\n') - meson_build.write('endforeach\n') - - meson_build.write('\n') + + recurse_subdirs = [] for subdir in subdirs: if subdir.name.startswith('_') or subdir.name.startswith('.'): continue @@ -179,7 +216,10 @@ def get_metadata(path: Path): meson_build.write(f"install_subdir('{subdir.name}', install_dir: sage_install_dir / '{folder_rel_to_src.relative_to('sage')}')\n") else: meson_build.write(f"subdir('{subdir.name}')\n") - run(subdir) + recurse_subdirs.append(subdir) + + for subdir in recurse_subdirs: + run(subdir, dry_run=dry_run, force=force) def generate_meson(): From 75bff50086c667066e058f6d499be9fc4f40f065 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 4 Jan 2024 22:43:35 -0800 Subject: [PATCH 07/30] sage-generate-meson: Go depth-first to collect distributions --- src/sage_setup/autogen/meson/__init__.py | 89 +++++++++++++++--------- 1 file changed, 57 insertions(+), 32 deletions(-) diff --git a/src/sage_setup/autogen/meson/__init__.py b/src/sage_setup/autogen/meson/__init__.py index 52d9d7ad252..9fa7b32b38f 100644 --- a/src/sage_setup/autogen/meson/__init__.py +++ b/src/sage_setup/autogen/meson/__init__.py @@ -10,6 +10,11 @@ from sage.misc.package_dir import read_distribution +def distribution_condition(distribution: str) -> str: + distribution_variable = 'distribution_' + distribution.replace('-', '_') + return f"get_variable('{distribution_variable}', false)" + + def run(folder: Path, dry_run=False, force=False): if not folder.is_dir(): @@ -17,13 +22,31 @@ def run(folder: Path, dry_run=False, force=False): return folder_rel_to_src = folder.relative_to('src') + recurse_subdirs = {} + by_distribution = defaultdict(lambda: SimpleNamespace(python_files=[], + cython_c_files=[], + cython_cpp_files=[], + install_subdirs=[])) + distributions = set() + subdirs = sorted(list(folder.glob('*/'))) + has_cython = False + + for subdir in subdirs: + if subdir.name.startswith('_') or subdir.name.startswith('.'): + continue + subdir_distributions, subdir_has_cython = run(subdir, dry_run=dry_run, force=force) + has_cython = has_cython or subdir_has_cython + if not subdir_distributions: + pass + elif len(subdir_distributions) > 1 or has_cython: + recurse_subdirs[subdir] = subdir_distributions + else: + by_distribution[list(subdir_distributions)[0]].install_subdirs.append(subdir) + distributions.update(subdir_distributions) + python_files = sorted(list(folder.glob('*.py')) + list(folder.glob('*.pxd')) + list(folder.glob('*.h'))) cython_files = sorted(list(folder.glob('*.pyx'))) - if not python_files and not cython_files: - print(f'Error: {folder} does not contain any python or cython files') - return - def get_metadata(path: Path): with open(path, 'r') as file: metadata = SimpleNamespace() @@ -129,30 +152,34 @@ def get_metadata(path: Path): cython_cpp_files = [file for file in cython_files if file.is_cpp] all_libraries = sorted(set(library for file in cython_files for library in file.libraries) | {'gmp'}) all_inc_dirs = sorted(set(inc_dir for file in cython_files for inc_dir in file.inc_dirs)) - subdirs = sorted(list(folder.glob('*/'))) meson_build_path = folder / 'meson.build' if not dry_run and not force and meson_build_path.exists(): print(f'Error: {meson_build_path} already exists, use --force to overwrite') return + for python_file in python_files: + by_distribution[python_file.distribution].python_files.append(python_file) + for cython_c_file in cython_c_files: + by_distribution[cython_c_file.distribution].cython_c_files.append(cython_c_file) + for cython_cpp_file in cython_cpp_files: + by_distribution[cython_cpp_file.distribution].cython_cpp_files.append(cython_cpp_file) + + distributions.update(by_distribution) + if cython_files: + has_cython = True + + if not has_cython and len(distributions) <= 1: + # No need for a meson.build file + return distributions, has_cython + print(f'Writing {meson_build_path}', file=sys.stderr) with open(meson_build_path, 'w') if not dry_run else sys.stdout as meson_build: - by_distribution = defaultdict(lambda: SimpleNamespace(python_files=[], - cython_c_files=[], - cython_cpp_files=[])) - for python_file in python_files: - by_distribution[python_file.distribution].python_files.append(python_file) - for cython_c_file in cython_c_files: - by_distribution[cython_c_file.distribution].cython_c_files.append(cython_c_file) - for cython_cpp_file in cython_cpp_files: - by_distribution[cython_cpp_file.distribution].cython_cpp_files.append(cython_cpp_file) - for distribution, files in by_distribution.items(): - distribution_variable = 'distribution_' + distribution.replace('-', '_') - meson_build.write(f"if get_variable('{distribution_variable}', false)\n") + if len(distributions) > 1: + meson_build.write(f"if {distribution_condition(distribution)}\n") if files.python_files: meson_build.write('py.install_sources(\n') @@ -202,24 +229,22 @@ def get_metadata(path: Path): meson_build.write(' )\n') meson_build.write('endforeach\n') - meson_build.write('endif\n') - meson_build.write('\n') + if files.install_subdirs: + for subdir in files.install_subdirs: + meson_build.write(f"install_subdir('{subdir.name}', install_dir: sage_install_dir / '{folder_rel_to_src.relative_to('sage')}')\n") + meson_build.write('\n') - recurse_subdirs = [] - for subdir in subdirs: - if subdir.name.startswith('_') or subdir.name.startswith('.'): - continue - if not list(subdir.glob('*.py*')): - continue + if len(distributions) > 1: + meson_build.write('endif ########################################################################\n') - if not list(subdir.glob('*.pyx')): - meson_build.write(f"install_subdir('{subdir.name}', install_dir: sage_install_dir / '{folder_rel_to_src.relative_to('sage')}')\n") - else: - meson_build.write(f"subdir('{subdir.name}')\n") - recurse_subdirs.append(subdir) + meson_build.write('\n') + + for subdir, subdir_distributions in recurse_subdirs.items(): + condition = " or ".join(distribution_condition(distribution) + for distribution in sorted(subdir_distributions)) + meson_build.write(f"if {condition}\n subdir('{subdir.name}')\nendif\n") - for subdir in recurse_subdirs: - run(subdir, dry_run=dry_run, force=force) + return distributions, has_cython def generate_meson(): From ca631474add46cd2906179bb965fb31145a62105 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sun, 31 Dec 2023 23:34:16 -0800 Subject: [PATCH 08/30] src/sage/meson.build.in: This is src/meson.build from PR Compile everything with meson (https://github.com/sagemath/sage/pull/36524 at 46bc6b4279c47c3f12c7da29f309b053a5cdb17c (2023-12-31) squashed on 10.3.beta4 --- src/sage/meson.build.in | 150 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 src/sage/meson.build.in diff --git a/src/sage/meson.build.in b/src/sage/meson.build.in new file mode 100644 index 00000000000..33a711816ee --- /dev/null +++ b/src/sage/meson.build.in @@ -0,0 +1,150 @@ +# Setup dependencies that are needed by many modules + +inc_numpy = run_command(py, + [ + '-c', + ''' +import numpy +print(numpy.get_include()) + '''.strip() + ], + check: true + ).stdout().strip() +numpy = declare_dependency( + include_directories: inc_numpy, +) + +inc_cysignals = run_command(py, + [ + '-c', + ''' +import cysignals +print(cysignals.__file__.replace('__init__.py', '')) + '''.strip() + ], + check: true + ).stdout().strip() +cysignals = declare_dependency( + include_directories: inc_cysignals, +) + +inc_gmpy2 = run_command(py, + [ + '-c', + ''' +import gmpy2 +print(gmpy2.__file__.replace('__init__.py', '')) + '''.strip() + ], + check: true + ).stdout().strip() +gmpy2 = declare_dependency( + include_directories: inc_gmpy2, +) +gmp = dependency('gmp', required: true) + +inc_cypari2 = run_command(py, + [ + '-c', + ''' +import cypari2 +print(cypari2.__file__.replace('__init__.py', '')) + '''.strip() + ], + check: true + ).stdout().strip() +cypari2 = declare_dependency( + include_directories: inc_cypari2, +) +pari = cc.find_library('pari') + +mpfr = cc.find_library('mpfr') + +# Cannot be found by pkg-config +flint = cc.find_library('flint') + +cblas = dependency('cblas') +gsl = dependency('gsl', fallback: ['gsl', 'gsl_dep'], version : '>=2.5', required: true) +gd = cc.find_library('gd') +iml = cc.find_library('iml') +m = cc.find_library('m') +m4ri = cc.find_library('m4ri') +m4rie = cc.find_library('m4rie') +mtx = cc.find_library('mtx', required: false) +png = cc.find_library('png') +zlib = cc.find_library('z') +intl = cc.find_library('intl', required: false) +curl = cc.find_library('curl') +# Cannot be found via pkg-config +ec = cc.find_library('ec') +ecm = cc.find_library('ecm') +# Cannot be found via pkg-config +glpk = cc.find_library('glpk') +ppl = cc.find_library('ppl') +gmpxx = cc.find_library('gmpxx') +readline = cc.find_library('readline') +lfunction = cc.find_library('Lfunction', required: false) +fflas = cc.find_library('fflas') +givaro = cc.find_library('givaro') +linbox = cc.find_library('linbox') +braiding = cc.find_library('braiding') +gc = cc.find_library('gc') +homfly = cc.find_library('homfly') +mpc = cc.find_library('mpc') +mpfi = cc.find_library('mpfi') +mpc = cc.find_library('mpc') +# Cannot be found via pkg-config +gap = cc.find_library('gap') + +singular = dependency('Singular') + +maxima = find_program('maxima', required: true) + +# Cannot be found via pkg-config +ntl = cc.find_library('ntl', required: true) + +# It's strange but cython cannot find its own include files +# so we find them ourselves, and add them to the include path +inc_cython = run_command(py, + [ + '-c', + ''' +import Cython +print(Cython.__file__.replace('__init__.py', '')) + '''.strip() + ], + check: true + ).stdout().strip() +add_project_arguments('-I', inc_cython + 'Includes', language : 'cython') + +# Meson currently ignores include_directories for Cython modules, so we +# have to add them manually. +# https://github.com/mesonbuild/meson/issues/9562 +add_project_arguments('-I', meson.current_source_dir(), language : 'cython') + +# Add global compiler flags +add_project_arguments('-X auto_pickle=False', language : 'cython') +add_project_arguments('-X autotestdict=False', language : 'cython') +add_project_arguments('-X binding=False', language : 'cython') +add_project_arguments('-X c_api_binop_methods=True', language : 'cython') +add_project_arguments('-X cdivision=True', language : 'cython') +add_project_arguments('-X cpow=True', language : 'cython') +add_project_arguments('-X embedsignature=True', language : 'cython') +add_project_arguments('--embed-positions', language : 'cython') +add_project_arguments('-X fast_getattr=True', language : 'cython') +#add_project_arguments('-X language_level="3"', language : 'cython') +add_project_arguments('-X legacy_implicit_noexcept=True', language : 'cython') +add_project_arguments('-X preliminary_late_includes_cy28=True', language : 'cython') + +inc_cpython = include_directories('sage/cpython') +inc_rings = include_directories('sage/rings') +inc_rings_finite = include_directories('sage/rings/finite_rings') +inc_flint = include_directories('sage/libs/flint') +inc_gsl = include_directories('sage/libs/gsl') +inc_ntl = include_directories('sage/libs/ntl') +inc_arb = include_directories('sage/libs/arb') +inc_data_structures = include_directories('sage/data_structures') +inc_ext = include_directories('sage/ext') +inc_interpreters = include_directories('sage/ext/interpreters') +inc_partn_ref2 = include_directories('sage/groups/perm_gps/partn_ref2') +inc_src = include_directories('.') From c5a1241c78b19700e5739ebe9a670648a5d51380 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 4 Jan 2024 23:43:33 -0800 Subject: [PATCH 09/30] sage-generate-meson: Paste meson.build.in if it exists --- src/sage_setup/autogen/meson/__init__.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/sage_setup/autogen/meson/__init__.py b/src/sage_setup/autogen/meson/__init__.py index 9fa7b32b38f..be7b3416d3e 100644 --- a/src/sage_setup/autogen/meson/__init__.py +++ b/src/sage_setup/autogen/meson/__init__.py @@ -176,6 +176,18 @@ def get_metadata(path: Path): print(f'Writing {meson_build_path}', file=sys.stderr) with open(meson_build_path, 'w') if not dry_run else sys.stdout as meson_build: + meson_build.write(f"# Automatically generated by sage-generate-meson; do not edit manually\n\n") + + try: + template_path = str(meson_build_path) + '.in' + with open(template_path, "r") as template: + meson_build.write(f"#line 1 {template_path}\n") + for line in template: + meson_build.write(line) + meson_build.write(f"\n# Automatically generated from here\n\n") + except FileNotFoundError: + pass + for distribution, files in by_distribution.items(): if len(distributions) > 1: From bb984d27e5ffc663d0ae63f5646099948f0d6a60 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sun, 31 Dec 2023 00:15:16 -0800 Subject: [PATCH 10/30] src/sage/meson.build.in: Add non-auto-generated bits from other meson.build files from PR Compile everything with meson (https://github.com/sagemath/sage/pull/36524 at 46bc6b4279c47c3f12c7da29f309b053a5cdb17c (2023-12-31) squashed on 10.3.beta4 --- src/sage/meson.build.in | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/sage/meson.build.in b/src/sage/meson.build.in index 33a711816ee..cabc7cd07a4 100644 --- a/src/sage/meson.build.in +++ b/src/sage/meson.build.in @@ -148,3 +148,12 @@ inc_ext = include_directories('sage/ext') inc_interpreters = include_directories('sage/ext/interpreters') inc_partn_ref2 = include_directories('sage/groups/perm_gps/partn_ref2') inc_src = include_directories('.') + +pthread = declare_dependency( + dependencies: [ + cc.find_library('pthread'), + ] +) + +inc_ginac = include_directories('symbolic/ginac') +inc_pynac = include_directories('symbolic') From d96efae4e227e64a5ab55e6d1778c14f89d718b2 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 5 Jan 2024 00:17:16 -0800 Subject: [PATCH 11/30] .gitignore: Ignore generated meson.build files --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 43f58abcafe..f171a6beeda 100644 --- a/.gitignore +++ b/.gitignore @@ -259,6 +259,9 @@ src/*.egg-info/ /src/bin/sage-env-config /src/bin/sage-src-env-config +# Generated by sage-generate-meson +/src/**/meson.build + # Virtual environments /venv src/.env From f08d1c21c3ac19bd00e29749b6261b9e6b6323ce Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 5 Jan 2024 00:18:49 -0800 Subject: [PATCH 12/30] sage-generate-meson: Fix up --- src/sage_setup/autogen/meson/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage_setup/autogen/meson/__init__.py b/src/sage_setup/autogen/meson/__init__.py index be7b3416d3e..3c45da8d161 100644 --- a/src/sage_setup/autogen/meson/__init__.py +++ b/src/sage_setup/autogen/meson/__init__.py @@ -38,7 +38,7 @@ def run(folder: Path, dry_run=False, force=False): has_cython = has_cython or subdir_has_cython if not subdir_distributions: pass - elif len(subdir_distributions) > 1 or has_cython: + elif len(subdir_distributions) > 1 or subdir_has_cython: recurse_subdirs[subdir] = subdir_distributions else: by_distribution[list(subdir_distributions)[0]].install_subdirs.append(subdir) @@ -132,7 +132,6 @@ def get_metadata(path: Path): '/linbox/': 'linbox', '/gsl/': 'gsl', 'mpfr.h': 'mpfr', - 'sage/symbolic/ginac/': 'ginac', 'arb.h': 'arb', 'mpfi.h': 'mpfi', 'mpc.h': 'mpc', @@ -171,6 +170,7 @@ def get_metadata(path: Path): if not has_cython and len(distributions) <= 1: # No need for a meson.build file + print(f'Not writing {meson_build_path}: distributions={sorted(distributions)}, {has_cython=}', file=sys.stderr) return distributions, has_cython print(f'Writing {meson_build_path}', file=sys.stderr) From 249935d166bba1d91356cf5b96d19d702ac1040f Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sun, 31 Dec 2023 11:16:51 -0800 Subject: [PATCH 13/30] src/sage/**/meson.build.in: Add non-auto-generated bits from other meson.build files from PR Compile everything with meson (https://github.com/sagemath/sage/pull/36524 at 46bc6b4279c47c3f12c7da29f309b053a5cdb17c (2023-12-31) squashed on 10.3.beta4 --- src/sage/ext/meson.build.in | 42 +++++++++++++++++++ .../graph_decompositions/meson.build.in | 7 ++++ src/sage/graphs/meson.build.in | 10 +++++ src/sage/libs/coxeter3/meson.build.in | 1 + src/sage/libs/giac/meson.build.in | 5 +++ src/sage/libs/meson.build.in | 7 ++++ src/sage/libs/symmetrica/meson.build.in | 6 +++ src/sage/matrix/meson.build.in | 11 +++++ src/sage/meson.build.in | 9 ---- src/sage/modular/arithgroup/meson.build.in | 7 ++++ src/sage/rings/meson.build.in | 5 +++ .../rings/polynomial/pbori/meson.build.in | 7 ++++ .../hyperelliptic_curves/meson.build.in | 1 + src/sage/symbolic/meson.build.in | 2 + 14 files changed, 111 insertions(+), 9 deletions(-) create mode 100644 src/sage/ext/meson.build.in create mode 100644 src/sage/graphs/graph_decompositions/meson.build.in create mode 100644 src/sage/graphs/meson.build.in create mode 100644 src/sage/libs/coxeter3/meson.build.in create mode 100644 src/sage/libs/giac/meson.build.in create mode 100644 src/sage/libs/meson.build.in create mode 100644 src/sage/libs/symmetrica/meson.build.in create mode 100644 src/sage/matrix/meson.build.in create mode 100644 src/sage/modular/arithgroup/meson.build.in create mode 100644 src/sage/rings/meson.build.in create mode 100644 src/sage/rings/polynomial/pbori/meson.build.in create mode 100644 src/sage/schemes/hyperelliptic_curves/meson.build.in create mode 100644 src/sage/symbolic/meson.build.in diff --git a/src/sage/ext/meson.build.in b/src/sage/ext/meson.build.in new file mode 100644 index 00000000000..365b1632c75 --- /dev/null +++ b/src/sage/ext/meson.build.in @@ -0,0 +1,42 @@ +interpreters = custom_target( + 'sage.ext.interpreters', + output: 'all.py', + input: '../../sage_setup/autogen/interpreters/__init__.py', + command: [py, '-m', 'sage_setup.autogen.interpreters', meson.current_source_dir() / 'interpreters'], + # This is actually against the Meson philosophy, which does not like in-source builds. + # So normally you would do something like the following + # however, this we currently cannot pass the generated files as sources to install_sources + # properly fixing this is left for a follow-up + # command: [py, '-m', 'sage_setup.autogen.interpreters','@OUTDIR@'], + env: ['PYTHONPATH=' + meson.current_source_dir() / '..' / '..'], +) + +# Manually create header files, which otherwise is not found +wrapper_el_header = custom_target( + 'wrapper_el.h', + output : 'wrapper_el.h', + input : ['interpreters/wrapper_el.pyx', interpreters], + command : [cython.cmd_array(), '@INPUT0@', '-o', '@OUTPUT@', '-I', join_paths(meson.current_source_dir(), '../../')], +) +wrapper_cc_header = custom_target( + 'wrapper_cc.h', + output : 'wrapper_cc.h', + input : ['interpreters/wrapper_cc.pyx', interpreters], + command : [cython.cmd_array(), '@INPUT0@', '-o', '@OUTPUT@', '-I', join_paths(meson.current_source_dir(), '../../')], +) +wrapper_cdf_header = custom_target( + 'wrapper_cdf.h', + output : 'wrapper_cdf.h', + input : ['interpreters/wrapper_cdf.pyx', interpreters], + command : [cython.cmd_array(), '@INPUT0@', '-o', '@OUTPUT@', '-I', join_paths(meson.current_source_dir(), '../../')], +) +wrapper_rr_header = custom_target( + 'wrapper_rr.h', + output : 'wrapper_rr.h', + input : ['interpreters/wrapper_rr.pyx', interpreters], + command : [cython.cmd_array(), '@INPUT0@', '-o', '@OUTPUT@', '-I', join_paths(meson.current_source_dir(), '../../')], +) + +interpreters_dep = declare_dependency( + sources: [interpreters, wrapper_el_header, wrapper_cc_header, wrapper_cdf_header, wrapper_rr_header], +) diff --git a/src/sage/graphs/graph_decompositions/meson.build.in b/src/sage/graphs/graph_decompositions/meson.build.in new file mode 100644 index 00000000000..1c4f674af8e --- /dev/null +++ b/src/sage/graphs/graph_decompositions/meson.build.in @@ -0,0 +1,7 @@ +tdlib = cc.find_library('tdlib', required: false) +# Cannot be found via pkg-config +rw = declare_dependency( + dependencies: [ + cc.find_library('rw'), + ] +) diff --git a/src/sage/graphs/meson.build.in b/src/sage/graphs/meson.build.in new file mode 100644 index 00000000000..963add61ce1 --- /dev/null +++ b/src/sage/graphs/meson.build.in @@ -0,0 +1,10 @@ +bliss = cc.find_library('bliss', required: false) +mcqd = cc.find_library('mcqd', required: false) +cliquer = cc.find_library('cliquer') + +# Cannot be found via pkg-config +planarity = declare_dependency( + dependencies: [ + cc.find_library('planarity'), + ] +) diff --git a/src/sage/libs/coxeter3/meson.build.in b/src/sage/libs/coxeter3/meson.build.in new file mode 100644 index 00000000000..eebd9806621 --- /dev/null +++ b/src/sage/libs/coxeter3/meson.build.in @@ -0,0 +1 @@ +coxeter3 = cc.find_library('coxeter3', required: false) diff --git a/src/sage/libs/giac/meson.build.in b/src/sage/libs/giac/meson.build.in new file mode 100644 index 00000000000..94990555c4c --- /dev/null +++ b/src/sage/libs/giac/meson.build.in @@ -0,0 +1,5 @@ +giac = declare_dependency( + dependencies: [ + cc.find_library('giac', required: false), + ] +) diff --git a/src/sage/libs/meson.build.in b/src/sage/libs/meson.build.in new file mode 100644 index 00000000000..a465e2cdd32 --- /dev/null +++ b/src/sage/libs/meson.build.in @@ -0,0 +1,7 @@ +sirocco = declare_dependency( + dependencies: [ + cc.find_library('sirocco', required: false), + ] +) +# cannot be found via pkg-config +ecl = cc.find_library('ecl') diff --git a/src/sage/libs/symmetrica/meson.build.in b/src/sage/libs/symmetrica/meson.build.in new file mode 100644 index 00000000000..e208969ecfc --- /dev/null +++ b/src/sage/libs/symmetrica/meson.build.in @@ -0,0 +1,6 @@ +# Cannot be found by pkg-config +symmetrica = declare_dependency( + dependencies: [ + cc.find_library('symmetrica'), + ] +) diff --git a/src/sage/matrix/meson.build.in b/src/sage/matrix/meson.build.in new file mode 100644 index 00000000000..1551376f8d9 --- /dev/null +++ b/src/sage/matrix/meson.build.in @@ -0,0 +1,11 @@ +# Cannot be found via pkg-config +meataxe = declare_dependency( + dependencies: [ + cc.find_library('meataxe', required: false), + ] +) +iml = declare_dependency( + dependencies: [ + cc.find_library('iml'), + ] +) diff --git a/src/sage/meson.build.in b/src/sage/meson.build.in index cabc7cd07a4..33a711816ee 100644 --- a/src/sage/meson.build.in +++ b/src/sage/meson.build.in @@ -148,12 +148,3 @@ inc_ext = include_directories('sage/ext') inc_interpreters = include_directories('sage/ext/interpreters') inc_partn_ref2 = include_directories('sage/groups/perm_gps/partn_ref2') inc_src = include_directories('.') - -pthread = declare_dependency( - dependencies: [ - cc.find_library('pthread'), - ] -) - -inc_ginac = include_directories('symbolic/ginac') -inc_pynac = include_directories('symbolic') diff --git a/src/sage/modular/arithgroup/meson.build.in b/src/sage/modular/arithgroup/meson.build.in new file mode 100644 index 00000000000..8a76d5edcd0 --- /dev/null +++ b/src/sage/modular/arithgroup/meson.build.in @@ -0,0 +1,7 @@ +# Manually create header file, which otherwise is not found +farey_symbol_header = custom_target( + 'farey_symbol.h', + output : 'farey_symbol.h', + input : 'farey_symbol.pyx', + command : [cython.cmd_array(), '--cplus', '@INPUT@', '-o', '@OUTPUT@', '-I', join_paths(meson.current_source_dir(), '../../../')], +) diff --git a/src/sage/rings/meson.build.in b/src/sage/rings/meson.build.in new file mode 100644 index 00000000000..d455898552a --- /dev/null +++ b/src/sage/rings/meson.build.in @@ -0,0 +1,5 @@ +pthread = declare_dependency( + dependencies: [ + cc.find_library('pthread'), + ] +) diff --git a/src/sage/rings/polynomial/pbori/meson.build.in b/src/sage/rings/polynomial/pbori/meson.build.in new file mode 100644 index 00000000000..ed5a4b421ee --- /dev/null +++ b/src/sage/rings/polynomial/pbori/meson.build.in @@ -0,0 +1,7 @@ +brial = declare_dependency( + dependencies: [ + cc.find_library('brial', required: false), + ] +) +# Cannot be found via pkg-config +brial_groebner = cc.find_library('brial_groebner') diff --git a/src/sage/schemes/hyperelliptic_curves/meson.build.in b/src/sage/schemes/hyperelliptic_curves/meson.build.in new file mode 100644 index 00000000000..ca45bd10f62 --- /dev/null +++ b/src/sage/schemes/hyperelliptic_curves/meson.build.in @@ -0,0 +1 @@ +inc_hypellfrob = include_directories('hypellfrob') diff --git a/src/sage/symbolic/meson.build.in b/src/sage/symbolic/meson.build.in new file mode 100644 index 00000000000..af62952ba40 --- /dev/null +++ b/src/sage/symbolic/meson.build.in @@ -0,0 +1,2 @@ +inc_ginac = include_directories('ginac') +inc_pynac = include_directories('.') From eb9bb7ef713c8ca0fdbc2aa3672756c45c927b5f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 5 Jan 2024 12:02:38 -0800 Subject: [PATCH 14/30] sage-generate-meson: Overwrite atomically, show diff --- src/sage_setup/autogen/meson/__init__.py | 39 +++++++++++++++++++++--- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/src/sage_setup/autogen/meson/__init__.py b/src/sage_setup/autogen/meson/__init__.py index 3c45da8d161..8e7e23bcf5f 100644 --- a/src/sage_setup/autogen/meson/__init__.py +++ b/src/sage_setup/autogen/meson/__init__.py @@ -4,7 +4,9 @@ import sys from collections import defaultdict +from difflib import unified_diff from pathlib import Path +from tempfile import NamedTemporaryFile from types import SimpleNamespace from sage.misc.package_dir import read_distribution @@ -15,6 +17,11 @@ def distribution_condition(distribution: str) -> str: return f"get_variable('{distribution_variable}', false)" +def log_update(operation, meson_build_path, distributions, has_cython): + main = f'{operation:12}{meson_build_path}' + print(f'{main:48}# ' + ' '.join(sorted(distributions)), file=sys.stderr) + + def run(folder: Path, dry_run=False, force=False): if not folder.is_dir(): @@ -170,11 +177,16 @@ def get_metadata(path: Path): if not has_cython and len(distributions) <= 1: # No need for a meson.build file - print(f'Not writing {meson_build_path}: distributions={sorted(distributions)}, {has_cython=}', file=sys.stderr) + try: + meson_build_path.unlink() + except FileNotFoundError: + print(f'Not writing {meson_build_path}: distributions={sorted(distributions)}, {has_cython=}', file=sys.stderr) + else: + print(f'Removing {meson_build_path}: distributions={sorted(distributions)}, {has_cython=}', file=sys.stderr) return distributions, has_cython - print(f'Writing {meson_build_path}', file=sys.stderr) - with open(meson_build_path, 'w') if not dry_run else sys.stdout as meson_build: + with NamedTemporaryFile(mode='w', prefix=meson_build_path.name, + dir=meson_build_path.parent, delete=False) if not dry_run else sys.stdout as meson_build: meson_build.write(f"# Automatically generated by sage-generate-meson; do not edit manually\n\n") @@ -256,7 +268,26 @@ def get_metadata(path: Path): for distribution in sorted(subdir_distributions)) meson_build.write(f"if {condition}\n subdir('{subdir.name}')\nendif\n") - return distributions, has_cython + meson_build_tmp_path = Path(meson_build.name) + + try: + with open(meson_build_path, "r") as old: + old_lines = list(old) + except FileNotFoundError: + print(f'Creating {meson_build_path}', file=sys.stderr) + else: + with open(meson_build_tmp_path, "r") as new: + new_lines = list(new) + changes = list(unified_diff(old_lines, new_lines, str(meson_build_path), str(meson_build.name))) + if changes: + meson_build_tmp_path.replace(meson_build_path) + print(f'Updating {meson_build_path}', file=sys.stderr) + sys.stdout.writelines(changes) + else: + print(f'Unchanged {meson_build_path}', file=sys.stderr) + meson_build_tmp_path.unlink() + + return distributions, has_cython def generate_meson(): From 0dd1a3fe4bf3e1b53e4216342f7eb41e3c1daa69 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 5 Jan 2024 12:36:39 -0800 Subject: [PATCH 15/30] sage-generate-meson: Better logging --- src/sage_setup/autogen/meson/__init__.py | 34 +++++++++++++++++++----- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/src/sage_setup/autogen/meson/__init__.py b/src/sage_setup/autogen/meson/__init__.py index 8e7e23bcf5f..34b408fd359 100644 --- a/src/sage_setup/autogen/meson/__init__.py +++ b/src/sage_setup/autogen/meson/__init__.py @@ -17,9 +17,29 @@ def distribution_condition(distribution: str) -> str: return f"get_variable('{distribution_variable}', false)" +def distributions_shorthand(distributions: set) -> str: + + sagemath_distributions = sorted(distribution.removeprefix('sagemath-') + for distribution in distributions + if distribution.startswith('sagemath-')) + distributions = sorted(distribution or "''" # the catch-all distribution + for distribution in distributions + if not distribution.startswith('sagemath-')) + if len(sagemath_distributions) > 1: + distributions.insert(0, 'sagemath-{' + ','.join(sagemath_distributions) + '}') + elif sagemath_distributions: + distributions.insert(0, 'sagemath-' + sagemath_distributions[0]) + if distributions: + return ', '.join(distributions) + return 'no distribution' + + def log_update(operation, meson_build_path, distributions, has_cython): - main = f'{operation:12}{meson_build_path}' - print(f'{main:48}# ' + ' '.join(sorted(distributions)), file=sys.stderr) + line = f'{operation:12}{meson_build_path}' + line = f'{line:62} # {distributions_shorthand(distributions)}' + if len(distributions) == 1 and has_cython: + line += ', has Cython modules' + print(line, file=sys.stderr) def run(folder: Path, dry_run=False, force=False): @@ -180,9 +200,9 @@ def get_metadata(path: Path): try: meson_build_path.unlink() except FileNotFoundError: - print(f'Not writing {meson_build_path}: distributions={sorted(distributions)}, {has_cython=}', file=sys.stderr) + log_update('Not writing', meson_build_path, distributions, has_cython) else: - print(f'Removing {meson_build_path}: distributions={sorted(distributions)}, {has_cython=}', file=sys.stderr) + log_update('Removing', meson_build_path, distributions, has_cython) return distributions, has_cython with NamedTemporaryFile(mode='w', prefix=meson_build_path.name, @@ -274,17 +294,17 @@ def get_metadata(path: Path): with open(meson_build_path, "r") as old: old_lines = list(old) except FileNotFoundError: - print(f'Creating {meson_build_path}', file=sys.stderr) + log_update('Creating', meson_build_path, distributions, has_cython) else: with open(meson_build_tmp_path, "r") as new: new_lines = list(new) changes = list(unified_diff(old_lines, new_lines, str(meson_build_path), str(meson_build.name))) if changes: meson_build_tmp_path.replace(meson_build_path) - print(f'Updating {meson_build_path}', file=sys.stderr) + log_update('Updating', meson_build_path, distributions, has_cython) sys.stdout.writelines(changes) else: - print(f'Unchanged {meson_build_path}', file=sys.stderr) + log_update('Unchanged', meson_build_path, distributions, has_cython) meson_build_tmp_path.unlink() return distributions, has_cython From 05b4db868de38af5d112a3d09cd050c6f608b724 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 5 Jan 2024 13:26:59 -0800 Subject: [PATCH 16/30] sage-generate-meson: Fix up creating files --- src/sage_setup/autogen/meson/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sage_setup/autogen/meson/__init__.py b/src/sage_setup/autogen/meson/__init__.py index 34b408fd359..1313a2d45aa 100644 --- a/src/sage_setup/autogen/meson/__init__.py +++ b/src/sage_setup/autogen/meson/__init__.py @@ -295,6 +295,7 @@ def get_metadata(path: Path): old_lines = list(old) except FileNotFoundError: log_update('Creating', meson_build_path, distributions, has_cython) + meson_build_tmp_path.rename(meson_build_path) else: with open(meson_build_tmp_path, "r") as new: new_lines = list(new) From e05f65d97d5dfbe3f7bac48cbccafb0bad9bc5ba Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 5 Jan 2024 14:15:01 -0800 Subject: [PATCH 17/30] sage-generate-meson: Add option --output-dir --- src/sage_setup/autogen/meson/__init__.py | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/sage_setup/autogen/meson/__init__.py b/src/sage_setup/autogen/meson/__init__.py index 1313a2d45aa..61fe75b1a15 100644 --- a/src/sage_setup/autogen/meson/__init__.py +++ b/src/sage_setup/autogen/meson/__init__.py @@ -1,6 +1,7 @@ # Small script that generates a meson.build file in the given folder. # The generated build file contains all python files as `install_sources` and all cython files as `extension_module` +import os import sys from collections import defaultdict @@ -42,7 +43,7 @@ def log_update(operation, meson_build_path, distributions, has_cython): print(line, file=sys.stderr) -def run(folder: Path, dry_run=False, force=False): +def run(folder: Path, output_dir: Path, dry_run=False, force=False): if not folder.is_dir(): print(f'Error: {folder} is not a directory') @@ -61,7 +62,7 @@ def run(folder: Path, dry_run=False, force=False): for subdir in subdirs: if subdir.name.startswith('_') or subdir.name.startswith('.'): continue - subdir_distributions, subdir_has_cython = run(subdir, dry_run=dry_run, force=force) + subdir_distributions, subdir_has_cython = run(subdir, output_dir / subdir.name, dry_run=dry_run, force=force) has_cython = has_cython or subdir_has_cython if not subdir_distributions: pass @@ -179,7 +180,8 @@ def get_metadata(path: Path): all_libraries = sorted(set(library for file in cython_files for library in file.libraries) | {'gmp'}) all_inc_dirs = sorted(set(inc_dir for file in cython_files for inc_dir in file.inc_dirs)) - meson_build_path = folder / 'meson.build' + template_path = folder / 'meson.build.in' + meson_build_path = output_dir / 'meson.build' if not dry_run and not force and meson_build_path.exists(): print(f'Error: {meson_build_path} already exists, use --force to overwrite') return @@ -205,13 +207,14 @@ def get_metadata(path: Path): log_update('Removing', meson_build_path, distributions, has_cython) return distributions, has_cython + os.makedirs(meson_build_path.parent, exist_ok=True) + with NamedTemporaryFile(mode='w', prefix=meson_build_path.name, dir=meson_build_path.parent, delete=False) if not dry_run else sys.stdout as meson_build: meson_build.write(f"# Automatically generated by sage-generate-meson; do not edit manually\n\n") try: - template_path = str(meson_build_path) + '.in' with open(template_path, "r") as template: meson_build.write(f"#line 1 {template_path}\n") for line in template: @@ -299,7 +302,7 @@ def get_metadata(path: Path): else: with open(meson_build_tmp_path, "r") as new: new_lines = list(new) - changes = list(unified_diff(old_lines, new_lines, str(meson_build_path), str(meson_build.name))) + changes = list(unified_diff(old_lines, new_lines, str(meson_build_path), str(os.path.relpath(meson_build_tmp_path)))) if changes: meson_build_tmp_path.replace(meson_build_path) log_update('Updating', meson_build_path, distributions, has_cython) @@ -320,10 +323,17 @@ def generate_meson(): parser.add_argument('--dry-run', '-n', action='store_true', help='do not write any files, just print the output') parser.add_argument('--force', '-f', action='store_true', - help='overwrite existing meson.build file') + help='overwrite existing meson.build files') + parser.add_argument('--output-dir', type=str, default=None, + help='folder where the generated meson.build files will be generated') args = parser.parse_args() folder = Path(args.folder) - run(folder, dry_run=args.dry_run, force=args.force) + if args.output_dir is None: + output_dir = folder + else: + output_dir = Path(args.output_dir) + + run(folder, output_dir, dry_run=args.dry_run, force=args.force) return 0 From f3ae437658d98657e1d104fb639d11aba18aeeaf Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 5 Jan 2024 15:32:50 -0800 Subject: [PATCH 18/30] sage-generate-meson: Add option --monolithic --- src/sage_setup/autogen/meson/__init__.py | 48 +++++++++++++++++------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/src/sage_setup/autogen/meson/__init__.py b/src/sage_setup/autogen/meson/__init__.py index 61fe75b1a15..daf90d7a732 100644 --- a/src/sage_setup/autogen/meson/__init__.py +++ b/src/sage_setup/autogen/meson/__init__.py @@ -10,8 +10,6 @@ from tempfile import NamedTemporaryFile from types import SimpleNamespace -from sage.misc.package_dir import read_distribution - def distribution_condition(distribution: str) -> str: distribution_variable = 'distribution_' + distribution.replace('-', '_') @@ -43,12 +41,26 @@ def log_update(operation, meson_build_path, distributions, has_cython): print(line, file=sys.stderr) -def run(folder: Path, output_dir: Path, dry_run=False, force=False): +def run(folder: Path, output_dir: Path, folder_rel_to_src=None, dry_run=False, force=False, monolithic=False): if not folder.is_dir(): print(f'Error: {folder} is not a directory') return - folder_rel_to_src = folder.relative_to('src') + try: + from sage.env import SAGE_SRC + except ImportError: + folder_rel_to_src = folder.relative_to('src') + else: + try: + folder_rel_to_src = folder.relative_to(SAGE_SRC) + except ValueError: + folder_rel_to_src = folder.resolve().relative_to(Path(SAGE_SRC).resolve()) + + if monolithic: + def read_distribution(path): + return '' + else: + from sage.misc.package_dir import read_distribution recurse_subdirs = {} by_distribution = defaultdict(lambda: SimpleNamespace(python_files=[], @@ -62,7 +74,8 @@ def run(folder: Path, output_dir: Path, dry_run=False, force=False): for subdir in subdirs: if subdir.name.startswith('_') or subdir.name.startswith('.'): continue - subdir_distributions, subdir_has_cython = run(subdir, output_dir / subdir.name, dry_run=dry_run, force=force) + subdir_distributions, subdir_has_cython = run(subdir, output_dir / subdir.name, + dry_run=dry_run, force=force, monolithic=monolithic) has_cython = has_cython or subdir_has_cython if not subdir_distributions: pass @@ -212,14 +225,17 @@ def get_metadata(path: Path): with NamedTemporaryFile(mode='w', prefix=meson_build_path.name, dir=meson_build_path.parent, delete=False) if not dry_run else sys.stdout as meson_build: - meson_build.write(f"# Automatically generated by sage-generate-meson; do not edit manually\n\n") + if not monolithic: + meson_build.write(f"# Automatically generated by sage-generate-meson; do not edit manually\n\n") try: with open(template_path, "r") as template: - meson_build.write(f"#line 1 {template_path}\n") + if not monolithic: + meson_build.write(f"#line 1 {template_path}\n") for line in template: meson_build.write(line) - meson_build.write(f"\n# Automatically generated from here\n\n") + if not monolithic: + meson_build.write(f"\n# Automatically generated from here\n\n") except FileNotFoundError: pass @@ -286,10 +302,14 @@ def get_metadata(path: Path): meson_build.write('\n') - for subdir, subdir_distributions in recurse_subdirs.items(): - condition = " or ".join(distribution_condition(distribution) - for distribution in sorted(subdir_distributions)) - meson_build.write(f"if {condition}\n subdir('{subdir.name}')\nendif\n") + if monolithic: + for subdir, _ in recurse_subdirs.items(): + meson_build.write(f"subdir('{subdir.name}')\n") + else: + for subdir, subdir_distributions in recurse_subdirs.items(): + condition = " or ".join(distribution_condition(distribution) + for distribution in sorted(subdir_distributions)) + meson_build.write(f"if {condition}\n subdir('{subdir.name}')\nendif\n") meson_build_tmp_path = Path(meson_build.name) @@ -326,6 +346,8 @@ def generate_meson(): help='overwrite existing meson.build files') parser.add_argument('--output-dir', type=str, default=None, help='folder where the generated meson.build files will be generated') + parser.add_argument('--monolithic', action='store_true', + help='ignore distributions') args = parser.parse_args() @@ -335,5 +357,5 @@ def generate_meson(): else: output_dir = Path(args.output_dir) - run(folder, output_dir, dry_run=args.dry_run, force=args.force) + run(folder, output_dir, dry_run=args.dry_run, force=args.force, monolithic=args.monolithic) return 0 From a1ecf3f19033bea8d56b5e0a496dc8b6921aa732 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 5 Jan 2024 15:44:22 -0800 Subject: [PATCH 19/30] sage-generate-meson: Improve option --monolithic --- src/sage_setup/autogen/meson/__init__.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/sage_setup/autogen/meson/__init__.py b/src/sage_setup/autogen/meson/__init__.py index daf90d7a732..3fd2865fd60 100644 --- a/src/sage_setup/autogen/meson/__init__.py +++ b/src/sage_setup/autogen/meson/__init__.py @@ -292,7 +292,7 @@ def get_metadata(path: Path): meson_build.write(' )\n') meson_build.write('endforeach\n') - if files.install_subdirs: + if not monolithic and files.install_subdirs: for subdir in files.install_subdirs: meson_build.write(f"install_subdir('{subdir.name}', install_dir: sage_install_dir / '{folder_rel_to_src.relative_to('sage')}')\n") meson_build.write('\n') @@ -303,8 +303,11 @@ def get_metadata(path: Path): meson_build.write('\n') if monolithic: - for subdir, _ in recurse_subdirs.items(): - meson_build.write(f"subdir('{subdir.name}')\n") + for subdir in sorted(set(recurse_subdirs).union(files.install_subdirs)): + if subdir in recurse_subdirs: + meson_build.write(f"subdir('{subdir.name}')\n") + else: + meson_build.write(f"install_subdir('{subdir.name}', install_dir: sage_install_dir / '{folder_rel_to_src.relative_to('sage')}')\n") else: for subdir, subdir_distributions in recurse_subdirs.items(): condition = " or ".join(distribution_condition(distribution) From 64a0f778d0a5876b808cdab971803dc7e1d971e8 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 5 Jan 2024 22:43:50 -0800 Subject: [PATCH 20/30] sage-generate-meson: Use install_subdir only when --monolithic --- src/sage_setup/autogen/meson/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage_setup/autogen/meson/__init__.py b/src/sage_setup/autogen/meson/__init__.py index 3fd2865fd60..0c700ee7f09 100644 --- a/src/sage_setup/autogen/meson/__init__.py +++ b/src/sage_setup/autogen/meson/__init__.py @@ -79,7 +79,7 @@ def read_distribution(path): has_cython = has_cython or subdir_has_cython if not subdir_distributions: pass - elif len(subdir_distributions) > 1 or subdir_has_cython: + elif not monolithic or len(subdir_distributions) > 1 or subdir_has_cython: recurse_subdirs[subdir] = subdir_distributions else: by_distribution[list(subdir_distributions)[0]].install_subdirs.append(subdir) @@ -210,7 +210,7 @@ def get_metadata(path: Path): if cython_files: has_cython = True - if not has_cython and len(distributions) <= 1: + if monolithic and not has_cython and len(distributions) <= 1: # No need for a meson.build file try: meson_build_path.unlink() From c0484eea89213f6101c0c44303531e1522a90b26 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 4 Jan 2024 21:19:59 -0800 Subject: [PATCH 21/30] pkgs/sagemath-objects: Draft meson --- build/pkgs/sagemath_objects/dependencies | 2 +- build/pkgs/sagemath_objects/spkg-install.in | 10 ++-- pkgs/sagemath-objects/meson.build | 64 +++++++++++++++++++++ pkgs/sagemath-objects/pyproject.toml.m4 | 5 +- 4 files changed, 73 insertions(+), 8 deletions(-) create mode 100644 pkgs/sagemath-objects/meson.build diff --git a/build/pkgs/sagemath_objects/dependencies b/build/pkgs/sagemath_objects/dependencies index ffc14bb6ba6..f0c41dd10a1 100644 --- a/build/pkgs/sagemath_objects/dependencies +++ b/build/pkgs/sagemath_objects/dependencies @@ -1,3 +1,3 @@ -FORCE cysignals gmpy2 | $(PYTHON_TOOLCHAIN) sagemath_environment sage_setup cython pkgconfig python_build $(PYTHON) +FORCE cysignals gmpy2 | $(PYTHON_TOOLCHAIN) sagemath_environment sage_setup cython pkgconfig python_build meson_python $(PYTHON) # FORCE: Always run the spkg-install script diff --git a/build/pkgs/sagemath_objects/spkg-install.in b/build/pkgs/sagemath_objects/spkg-install.in index 62cb1b73b22..a9b03e706d9 100644 --- a/build/pkgs/sagemath_objects/spkg-install.in +++ b/build/pkgs/sagemath_objects/spkg-install.in @@ -1,14 +1,16 @@ cd src +# For meson +export CXX=$(echo "$CXX" | sed 's/-std=[a-z0-9+]*//g') +export CYTHON=sage-cython +export CYTHON_FOR_BUILD=sage-cython + export PIP_NO_INDEX=true export PIP_FIND_LINKS="file://$SAGE_SPKG_WHEELS" -# First build the sdist, then build the wheel from the sdist. -# https://pypa-build.readthedocs.io/en/latest/#python--m-build -# (Important because sagemath-objects uses MANIFEST.in for filtering.) # Do not install the wheel. DIST_DIR="$(mktemp -d)" -python3 -m build --outdir "$DIST_DIR"/dist . || sdh_die "Failure building sdist and wheel" +python3 -m build --no-isolation --wheel --skip-dependency-check --outdir "$DIST_DIR"/dist . || sdh_die "Failure building sdist and wheel" wheel=$(cd "$DIST_DIR" && sdh_store_wheel . >&2 && echo $wheel) ls -l "$wheel" diff --git a/pkgs/sagemath-objects/meson.build b/pkgs/sagemath-objects/meson.build new file mode 100644 index 00000000000..bf35925e9fd --- /dev/null +++ b/pkgs/sagemath-objects/meson.build @@ -0,0 +1,64 @@ +project( + 'sagemath-objects', + ['c', 'cpp', 'cython'], + version: files('VERSION.txt'), + meson_version: '>= 1.2.0', +) + +set_variable('distribution_sagemath_objects', true) + +# Python module +# https://mesonbuild.com/Python-module.html +py_module = import('python') +py = py_module.find_installation(pure: false) +py_dep = py.dependency() + +# Compilers +cc = meson.get_compiler('c') +cpp = meson.get_compiler('cpp') +cython = meson.get_compiler('cython') + +py.install_sources( + 'sage/cpython/__init__.py', + 'sage/cpython/_py2_random.py', + 'sage/cpython/all.py', + 'sage/cpython/cython_metaclass.h', + 'sage/cpython/cython_metaclass.pxd', + 'sage/cpython/dict_del_by_value.pxd', + 'sage/cpython/dict_internal.h', + 'sage/cpython/getattr.pxd', + 'sage/cpython/pycore_long.h', + 'sage/cpython/pycore_long.pxd', + 'sage/cpython/python_debug.h', + 'sage/cpython/python_debug.pxd', + 'sage/cpython/pyx_visit.h', + 'sage/cpython/string.pxd', + 'sage/cpython/string_impl.h', + 'sage/cpython/type.pxd', + 'sage/cpython/wrapperdescr.pxd', + subdir: 'sage/cpython/', +) + +extension_data = { + 'atexit': files('sage/cpython/atexit.pyx'), + 'builtin_types': files('sage/cpython/builtin_types.pyx'), + 'cython_metaclass': files('sage/cpython/cython_metaclass.pyx'), + 'debug': files('sage/cpython/debug.pyx'), + 'dict_del_by_value': files('sage/cpython/dict_del_by_value.pyx'), + 'getattr': files('sage/cpython/getattr.pyx'), + 'string': files('sage/cpython/string.pyx'), + 'type': files('sage/cpython/type.pyx'), + 'wrapperdescr': files('sage/cpython/wrapperdescr.pyx'), +} + +if get_variable('distribution_sagemath_objects', false) +foreach name, pyx : extension_data + py.extension_module(name, + sources: pyx, + install: true, + subdir: 'sage/cpython/', + include_directories: include_directories('sage/cpython/'), + dependencies: [py_dep], + ) +endforeach +endif diff --git a/pkgs/sagemath-objects/pyproject.toml.m4 b/pkgs/sagemath-objects/pyproject.toml.m4 index a8d7d83a44a..c047ba3e327 100644 --- a/pkgs/sagemath-objects/pyproject.toml.m4 +++ b/pkgs/sagemath-objects/pyproject.toml.m4 @@ -2,8 +2,7 @@ include(`sage_spkg_versions_toml.m4')dnl' -*- conf-toml -*- [build-system] # Minimum requirements for the build system to execute. requires = [ - SPKG_INSTALL_REQUIRES_setuptools - SPKG_INSTALL_REQUIRES_wheel + SPKG_INSTALL_REQUIRES_meson_python SPKG_INSTALL_REQUIRES_sage_setup SPKG_INSTALL_REQUIRES_sagemath_environment SPKG_INSTALL_REQUIRES_cython @@ -11,7 +10,7 @@ requires = [ SPKG_INSTALL_REQUIRES_cysignals SPKG_INSTALL_REQUIRES_pkgconfig ] -build-backend = "setuptools.build_meta" +build-backend = "mesonpy" [project] name = "sagemath-objects" From 9aa11d96dc36fb4678f71471422b0ad4961a9569 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 4 Jan 2024 23:44:08 -0800 Subject: [PATCH 22/30] pkgs/sagemath-objects/meson.build: Use subdir('sage') --- pkgs/sagemath-objects/meson.build | 45 ++----------------------------- src/sage/meson.build.in | 24 +++++++++-------- 2 files changed, 15 insertions(+), 54 deletions(-) diff --git a/pkgs/sagemath-objects/meson.build b/pkgs/sagemath-objects/meson.build index bf35925e9fd..b0e64d56aa2 100644 --- a/pkgs/sagemath-objects/meson.build +++ b/pkgs/sagemath-objects/meson.build @@ -18,47 +18,6 @@ cc = meson.get_compiler('c') cpp = meson.get_compiler('cpp') cython = meson.get_compiler('cython') -py.install_sources( - 'sage/cpython/__init__.py', - 'sage/cpython/_py2_random.py', - 'sage/cpython/all.py', - 'sage/cpython/cython_metaclass.h', - 'sage/cpython/cython_metaclass.pxd', - 'sage/cpython/dict_del_by_value.pxd', - 'sage/cpython/dict_internal.h', - 'sage/cpython/getattr.pxd', - 'sage/cpython/pycore_long.h', - 'sage/cpython/pycore_long.pxd', - 'sage/cpython/python_debug.h', - 'sage/cpython/python_debug.pxd', - 'sage/cpython/pyx_visit.h', - 'sage/cpython/string.pxd', - 'sage/cpython/string_impl.h', - 'sage/cpython/type.pxd', - 'sage/cpython/wrapperdescr.pxd', - subdir: 'sage/cpython/', -) - -extension_data = { - 'atexit': files('sage/cpython/atexit.pyx'), - 'builtin_types': files('sage/cpython/builtin_types.pyx'), - 'cython_metaclass': files('sage/cpython/cython_metaclass.pyx'), - 'debug': files('sage/cpython/debug.pyx'), - 'dict_del_by_value': files('sage/cpython/dict_del_by_value.pyx'), - 'getattr': files('sage/cpython/getattr.pyx'), - 'string': files('sage/cpython/string.pyx'), - 'type': files('sage/cpython/type.pyx'), - 'wrapperdescr': files('sage/cpython/wrapperdescr.pyx'), -} +set_variable('distribution_sagemath_objects', true) -if get_variable('distribution_sagemath_objects', false) -foreach name, pyx : extension_data - py.extension_module(name, - sources: pyx, - install: true, - subdir: 'sage/cpython/', - include_directories: include_directories('sage/cpython/'), - dependencies: [py_dep], - ) -endforeach -endif +subdir('sage') diff --git a/src/sage/meson.build.in b/src/sage/meson.build.in index 33a711816ee..ccb98c1e9e9 100644 --- a/src/sage/meson.build.in +++ b/src/sage/meson.build.in @@ -1,5 +1,7 @@ # Setup dependencies that are needed by many modules +sage_install_dir = py.get_install_dir() / 'sage' + inc_numpy = run_command(py, [ '-c', @@ -136,15 +138,15 @@ add_project_arguments('-X fast_getattr=True', language : 'cython') add_project_arguments('-X legacy_implicit_noexcept=True', language : 'cython') add_project_arguments('-X preliminary_late_includes_cy28=True', language : 'cython') -inc_cpython = include_directories('sage/cpython') -inc_rings = include_directories('sage/rings') -inc_rings_finite = include_directories('sage/rings/finite_rings') -inc_flint = include_directories('sage/libs/flint') -inc_gsl = include_directories('sage/libs/gsl') -inc_ntl = include_directories('sage/libs/ntl') -inc_arb = include_directories('sage/libs/arb') -inc_data_structures = include_directories('sage/data_structures') -inc_ext = include_directories('sage/ext') -inc_interpreters = include_directories('sage/ext/interpreters') -inc_partn_ref2 = include_directories('sage/groups/perm_gps/partn_ref2') +inc_cpython = include_directories('cpython') +inc_rings = include_directories('rings') +inc_rings_finite = include_directories('rings/finite_rings') +inc_flint = include_directories('libs/flint') +inc_gsl = include_directories('libs/gsl') +inc_ntl = include_directories('libs/ntl') +inc_arb = include_directories('libs/arb') +inc_data_structures = include_directories('data_structures') +inc_ext = include_directories('ext') +inc_interpreters = include_directories('ext/interpreters') +inc_partn_ref2 = include_directories('groups/perm_gps/partn_ref2') inc_src = include_directories('.') From 0b1dcba364e2585763dfbf664a9399d29c6c7ff7 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sun, 31 Dec 2023 00:15:16 -0800 Subject: [PATCH 23/30] src/sage/meson.build.in: Add non-auto-generated bits from other meson.build files from PR Compile everything with meson (https://github.com/sagemath/sage/pull/36524 at 46bc6b4279c47c3f12c7da29f309b053a5cdb17c (2023-12-31) squashed on 10.3.beta4 --- src/sage/meson.build.in | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/sage/meson.build.in b/src/sage/meson.build.in index ccb98c1e9e9..86dceb29ca5 100644 --- a/src/sage/meson.build.in +++ b/src/sage/meson.build.in @@ -150,3 +150,12 @@ inc_ext = include_directories('ext') inc_interpreters = include_directories('ext/interpreters') inc_partn_ref2 = include_directories('groups/perm_gps/partn_ref2') inc_src = include_directories('.') + +pthread = declare_dependency( + dependencies: [ + cc.find_library('pthread'), + ] +) + +inc_ginac = include_directories('symbolic/ginac') +inc_pynac = include_directories('symbolic') From d7643d7f0a1833e033374a3060ae4f5d09a96446 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 5 Jan 2024 00:18:32 -0800 Subject: [PATCH 24/30] pkgs/sagemath-objects/meson.build: Fixup --- pkgs/sagemath-objects/meson.build | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkgs/sagemath-objects/meson.build b/pkgs/sagemath-objects/meson.build index b0e64d56aa2..22b3ef90dbe 100644 --- a/pkgs/sagemath-objects/meson.build +++ b/pkgs/sagemath-objects/meson.build @@ -18,6 +18,4 @@ cc = meson.get_compiler('c') cpp = meson.get_compiler('cpp') cython = meson.get_compiler('cython') -set_variable('distribution_sagemath_objects', true) - subdir('sage') From f45d0f3b114c82c874371cb774a7cebae082b195 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 5 Jan 2024 00:19:16 -0800 Subject: [PATCH 25/30] pkgs/sagemath-categories: Switch build system to meson-python --- build/pkgs/sagemath_categories/dependencies | 2 +- pkgs/sagemath-categories/meson.build | 21 +++++++++++++++++++++ pkgs/sagemath-categories/pyproject.toml.m4 | 5 ++--- 3 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 pkgs/sagemath-categories/meson.build diff --git a/build/pkgs/sagemath_categories/dependencies b/build/pkgs/sagemath_categories/dependencies index 9fa43a64aae..de4c33c803c 100644 --- a/build/pkgs/sagemath_categories/dependencies +++ b/build/pkgs/sagemath_categories/dependencies @@ -1 +1 @@ - sagemath_objects | $(PYTHON_TOOLCHAIN) sagemath_environment sage_setup cython pkgconfig python_build $(PYTHON) + sagemath_objects | $(PYTHON_TOOLCHAIN) sagemath_environment sage_setup cython pkgconfig python_build meson_python $(PYTHON) diff --git a/pkgs/sagemath-categories/meson.build b/pkgs/sagemath-categories/meson.build new file mode 100644 index 00000000000..3f6621a48ab --- /dev/null +++ b/pkgs/sagemath-categories/meson.build @@ -0,0 +1,21 @@ +project( + 'sagemath-categories', + ['c', 'cpp', 'cython'], + version: files('VERSION.txt'), + meson_version: '>= 1.2.0', +) + +set_variable('distribution_sagemath_categories', true) + +# Python module +# https://mesonbuild.com/Python-module.html +py_module = import('python') +py = py_module.find_installation(pure: false) +py_dep = py.dependency() + +# Compilers +cc = meson.get_compiler('c') +cpp = meson.get_compiler('cpp') +cython = meson.get_compiler('cython') + +subdir('sage') diff --git a/pkgs/sagemath-categories/pyproject.toml.m4 b/pkgs/sagemath-categories/pyproject.toml.m4 index eed48a1db15..c0f4fbb523a 100644 --- a/pkgs/sagemath-categories/pyproject.toml.m4 +++ b/pkgs/sagemath-categories/pyproject.toml.m4 @@ -2,8 +2,7 @@ include(`sage_spkg_versions_toml.m4')dnl' -*- conf-toml -*- [build-system] # Minimum requirements for the build system to execute. requires = [ - SPKG_INSTALL_REQUIRES_setuptools - SPKG_INSTALL_REQUIRES_wheel + SPKG_INSTALL_REQUIRES_meson_python SPKG_INSTALL_REQUIRES_sage_setup SPKG_INSTALL_REQUIRES_sagemath_environment SPKG_INSTALL_REQUIRES_sagemath_objects @@ -12,7 +11,7 @@ requires = [ SPKG_INSTALL_REQUIRES_cysignals SPKG_INSTALL_REQUIRES_pkgconfig ] -build-backend = "setuptools.build_meta" +build-backend = "mesonpy" [project] name = "sagemath-categories" From 9f63d703cc4edddd835fe9e5f54dfb36865b4346 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sun, 31 Dec 2023 11:16:51 -0800 Subject: [PATCH 26/30] src/sage/**/meson.build.in: Add non-auto-generated bits from other meson.build files from PR Compile everything with meson (https://github.com/sagemath/sage/pull/36524 at 46bc6b4279c47c3f12c7da29f309b053a5cdb17c (2023-12-31) squashed on 10.3.beta4 --- src/sage/meson.build.in | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/sage/meson.build.in b/src/sage/meson.build.in index 86dceb29ca5..ccb98c1e9e9 100644 --- a/src/sage/meson.build.in +++ b/src/sage/meson.build.in @@ -150,12 +150,3 @@ inc_ext = include_directories('ext') inc_interpreters = include_directories('ext/interpreters') inc_partn_ref2 = include_directories('groups/perm_gps/partn_ref2') inc_src = include_directories('.') - -pthread = declare_dependency( - dependencies: [ - cc.find_library('pthread'), - ] -) - -inc_ginac = include_directories('symbolic/ginac') -inc_pynac = include_directories('symbolic') From bde3778ebc324488f194f9bf88a47e518d972ef2 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 5 Jan 2024 13:31:27 -0800 Subject: [PATCH 27/30] Switch pkgs/sagemath-standard ('make SAGE_WHEELS=yes sagelib') to meson-python --- .gitignore | 1 + build/pkgs/sagelib/spkg-install.in | 9 +- pkgs/sagemath-standard/meson.build | 50 +++++ .../pyproject-monolithic.toml.m4 | 1 + pkgs/sagemath-standard/pyproject.toml | 173 +++++++++++++++++- pkgs/sagemath-standard/pyproject.toml.m4 | 161 +++++++++++++++- 6 files changed, 392 insertions(+), 3 deletions(-) create mode 100644 pkgs/sagemath-standard/meson.build create mode 120000 pkgs/sagemath-standard/pyproject-monolithic.toml.m4 mode change 120000 => 100644 pkgs/sagemath-standard/pyproject.toml mode change 120000 => 100644 pkgs/sagemath-standard/pyproject.toml.m4 diff --git a/.gitignore b/.gitignore index f171a6beeda..6d58fac0d3d 100644 --- a/.gitignore +++ b/.gitignore @@ -234,6 +234,7 @@ build/bin/sage-build-env-config /pkgs/sagemath-environment/requirements.txt /pkgs/sagemath-repl/requirements.txt /pkgs/sagemath-categories/MANIFEST.in +/pkgs/sagemath-standard/pyproject-monolithic.toml # same for old locations - before Issue #31577 /build/pkgs/*/src/build diff --git a/build/pkgs/sagelib/spkg-install.in b/build/pkgs/sagelib/spkg-install.in index 39ffc25f270..c67e5c28a72 100644 --- a/build/pkgs/sagelib/spkg-install.in +++ b/build/pkgs/sagelib/spkg-install.in @@ -41,6 +41,13 @@ unset SAGE_PKG_CONFIG_PATH # spec, which includes setting a symlink to the installed documentation. # export SAGE_DOC=/doesnotexist +if [ "$SAGE_WHEELS" = yes ]; then + # For meson + export CXX=$(echo "$CXX" | sed 's/-std=[a-z0-9+]*//g') + export CYTHON=sage-cython + export CYTHON_FOR_BUILD=sage-cython +fi + SITEPACKAGESDIR=$(python3 -c 'import sysconfig; print(sysconfig.get_paths()["purelib"])') export SAGE_OPTIONAL_PACKAGES_WITH_EXTENSIONS="" @@ -57,7 +64,7 @@ if [ "$SAGE_EDITABLE" = yes ]; then if [ "$SAGE_WHEELS" = yes ]; then # Additionally build a wheel (for use in other venvs) - cd $SAGE_PKGS/sagelib/src && time sdh_setup_bdist_wheel && sdh_store_wheel . + cd $SAGE_PKGS/sagelib/src && time python3 -m build --no-isolation --wheel --skip-dependency-check . && sdh_store_wheel . fi else # Make sure that an installed old version of sagelib in which sage is an ordinary package diff --git a/pkgs/sagemath-standard/meson.build b/pkgs/sagemath-standard/meson.build new file mode 100644 index 00000000000..243f048a530 --- /dev/null +++ b/pkgs/sagemath-standard/meson.build @@ -0,0 +1,50 @@ +project( + 'sagemath-standard', + ['c', 'cpp', 'cython'], + version: files('VERSION.txt'), + meson_version: '>= 1.2.0', +) + +# same list in setup.py +set_variable('distribution_', true) # catch-all +set_variable('distribution_sagemath_objects', true) +set_variable('distribution_sagemath_brial', true) +set_variable('distribution_sagemath_categories', true) +set_variable('distribution_sagemath_combinat', true) +set_variable('distribution_sagemath_eclib', true) +set_variable('distribution_sagemath_environment', true) +set_variable('distribution_sagemath_flint', true) +set_variable('distribution_sagemath_gap', true) +set_variable('distribution_sagemath_giac', true) +set_variable('distribution_sagemath_glpk', true) +set_variable('distribution_sagemath_graphs', true) +set_variable('distribution_sagemath_groups', true) +set_variable('distribution_sagemath_homfly', true) +set_variable('distribution_sagemath_lcalc', true) +set_variable('distribution_sagemath_libbraiding', true) +set_variable('distribution_sagemath_libecm', true) +set_variable('distribution_sagemath_linbox', true) +set_variable('distribution_sagemath_modules', true) +set_variable('distribution_sagemath_mpmath', true) +set_variable('distribution_sagemath_ntl', true) +set_variable('distribution_sagemath_objects', true) +set_variable('distribution_sagemath_pari', true) +set_variable('distribution_sagemath_plot', true) +set_variable('distribution_sagemath_polyhedra', true) +set_variable('distribution_sagemath_repl', true) +set_variable('distribution_sagemath_schemes', true) +set_variable('distribution_sagemath_singular', true) +set_variable('distribution_sagemath_symbolics', true) + +# Python module +# https://mesonbuild.com/Python-module.html +py_module = import('python') +py = py_module.find_installation(pure: false) +py_dep = py.dependency() + +# Compilers +cc = meson.get_compiler('c') +cpp = meson.get_compiler('cpp') +cython = meson.get_compiler('cython') + +subdir('sage') diff --git a/pkgs/sagemath-standard/pyproject-monolithic.toml.m4 b/pkgs/sagemath-standard/pyproject-monolithic.toml.m4 new file mode 120000 index 00000000000..25dbae84866 --- /dev/null +++ b/pkgs/sagemath-standard/pyproject-monolithic.toml.m4 @@ -0,0 +1 @@ +../../src/pyproject.toml.m4 \ No newline at end of file diff --git a/pkgs/sagemath-standard/pyproject.toml b/pkgs/sagemath-standard/pyproject.toml deleted file mode 120000 index ef15d0eea45..00000000000 --- a/pkgs/sagemath-standard/pyproject.toml +++ /dev/null @@ -1 +0,0 @@ -../../src/pyproject.toml \ No newline at end of file diff --git a/pkgs/sagemath-standard/pyproject.toml b/pkgs/sagemath-standard/pyproject.toml new file mode 100644 index 00000000000..f95d4bbe1d8 --- /dev/null +++ b/pkgs/sagemath-standard/pyproject.toml @@ -0,0 +1,172 @@ +# Generated by SAGE_ROOT/bootstrap; do not edit +[build-system] +# Minimum requirements for the build system to execute. +requires = [ + 'meson-python', + "sage_setup[autogen]", + # Some version of sage-conf is required. + # Note that PEP517/518 have no notion of optional sage_spkg dependencies: + # https://github.com/pypa/pip/issues/6144 + 'sage-conf ~= 10.3b4', + 'sage-setup ~= 10.3b4', + 'cypari2 >=2.1.1', + 'cysignals >=1.10.2', + 'cython >=3.0, != 3.0.3, <4.0', + 'gmpy2 >=2.1.0', + 'jupyter_core >=4.6.3', + 'memory_allocator', + 'numpy >=1.19', + 'pkgconfig', + 'pplpy >=0.8.6', +] +build-backend = "mesonpy" + +[project] +name = "sagemath-standard" +description = "Sage: Open Source Mathematics Software: Standard Python Library" +dependencies = [ + 'sage-conf ~= 10.3b4', + 'six >=1.15.0', + 'conway-polynomials >=0.8', + 'cypari2 >=2.1.1', + 'cysignals >=1.10.2', + 'cython >=3.0, != 3.0.3, <4.0', + 'gmpy2 >=2.1.0', + 'importlib_metadata >=4.13', + 'importlib_resources >= 5.7', + 'jupyter_core >=4.6.3', + 'lrcalc ~=2.1', + 'memory_allocator', + 'numpy >=1.19', + 'pkgconfig', + 'pplpy >=0.8.6', + 'primecountpy', + 'requests >=2.13.0', + 'typing_extensions >= 4.4.0', + 'ipython >=7.13.0', + 'pexpect >=4.8.0', + 'sphinx >=5.2, <8', + 'networkx >=2.4, <3.3', + 'scipy >=1.5, <1.12', + 'sympy >=1.6, <2.0', + 'matplotlib >=3.5.1', + 'pillow >=7.2.0', + 'mpmath >=1.1.0', + 'ipykernel >=5.2.1', + 'jupyter-client', + 'ipywidgets >=7.5.1', + 'fpylll >=0.5.9', + 'ptyprocess > 0.5', +] +dynamic = ["version"] +license = {text = "GNU General Public License (GPL) v2 or later"} +authors = [{name = "The Sage Developers", email = "sage-support@googlegroups.com"}] +classifiers = [ + "Development Status :: 6 - Mature", + "Intended Audience :: Education", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)", + "Operating System :: POSIX", + "Operating System :: MacOS :: MacOS X", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: Implementation :: CPython", + "Topic :: Scientific/Engineering :: Mathematics", +] +urls = {Homepage = "https://www.sagemath.org"} +requires-python = ">=3.9, <3.12" + +[project.optional-dependencies] +R = [ + 'rpy2 >=3.3', +] + +[project.readme] +file = "README.rst" +content-type = "text/x-rst" + +[tool.conda-lock] +platforms = [ + 'osx-64', 'linux-64', 'linux-aarch64', 'osx-arm64' +] + +[tool.setuptools] +script-files = [ + # The sage script + "bin/sage", + # Other scripts that should be in the path also for OS packaging of sage: + "bin/sage-eval", + # Included because it is useful for doctesting/coverage testing user scripts too: + "bin/sage-runtests", + "bin/sage-fixdoctests", + "bin/sage-coverage", + # The following is deprecated but might still be used in user package install scripts + "bin/sage-cython", + # Helper scripts invoked by sage script + # (they would actually belong to something like libexec) + "bin/sage-cachegrind", + "bin/sage-callgrind", + "bin/sage-massif", + "bin/sage-omega", + "bin/sage-valgrind", + "bin/sage-venv-config", + "bin/sage-version.sh", + "bin/sage-cleaner", + # Only makes sense in sage-the-distribution. TODO: Move to another installation script. + "bin/sage-list-packages", + # Uncategorized scripts in alphabetical order + "bin/math-readline", + "bin/sage-env", + # sage-env-config -- installed by sage_conf + # sage-env-config.in -- not to be installed + "bin/sage-grep", + "bin/sage-grepdoc", + "bin/sage-inline-fortran", + "bin/sage-ipynb2rst", + "bin/sage-ipython", + "bin/sage-notebook", + "bin/sage-num-threads.py", + "bin/sage-preparse", + "bin/sage-python", + "bin/sage-run", + "bin/sage-run-cython", + "bin/sage-startuptime.py", + "bin/sage-update-version", +] +license-files = ["LICENSE.txt"] +include-package-data = false + +[tool.setuptools.package-data] +"sage.libs.gap" = ["sage.gaprc"] +"sage.interfaces" = ["sage-maxima.lisp"] +"sage.doctest" = ["tests/*"] +"sage.repl.rich_output" = ["example*"] +sage = [ + "ext_data/*", + "ext_data/kenzo/*", + "ext_data/singular/*", + "ext_data/singular/function_field/*", + "ext_data/images/*", + "ext_data/doctest/*", + "ext_data/doctest/invalid/*", + "ext_data/gap/*", + "ext_data/gap/joyner/*", + "ext_data/mwrank/*", + "ext_data/notebook-ipython/*", + "ext_data/nbconvert/*", + "ext_data/graphs/*", + "ext_data/pari/*", + "ext_data/pari/dokchitser/*", + "ext_data/pari/buzzard/*", + "ext_data/pari/simon/*", + "ext_data/magma/*", + "ext_data/magma/latex/*", + "ext_data/magma/sage/*", + "ext_data/valgrind/*", + "ext_data/threejs/*", +] + +[tool.setuptools.dynamic] +version = {file = ["VERSION.txt"]} diff --git a/pkgs/sagemath-standard/pyproject.toml.m4 b/pkgs/sagemath-standard/pyproject.toml.m4 deleted file mode 120000 index 25dbae84866..00000000000 --- a/pkgs/sagemath-standard/pyproject.toml.m4 +++ /dev/null @@ -1 +0,0 @@ -../../src/pyproject.toml.m4 \ No newline at end of file diff --git a/pkgs/sagemath-standard/pyproject.toml.m4 b/pkgs/sagemath-standard/pyproject.toml.m4 new file mode 100644 index 00000000000..1b3bb213717 --- /dev/null +++ b/pkgs/sagemath-standard/pyproject.toml.m4 @@ -0,0 +1,160 @@ +include(`sage_spkg_versions_toml.m4')dnl' -*- conf-toml -*- +[build-system] +# Minimum requirements for the build system to execute. +requires = [ + SPKG_INSTALL_REQUIRES_meson_python + "sage_setup[autogen]", + # Some version of sage-conf is required. + # Note that PEP517/518 have no notion of optional sage_spkg dependencies: + # https://github.com/pypa/pip/issues/6144 + SPKG_INSTALL_REQUIRES_sage_conf + SPKG_INSTALL_REQUIRES_sage_setup + SPKG_INSTALL_REQUIRES_cypari + SPKG_INSTALL_REQUIRES_cysignals + SPKG_INSTALL_REQUIRES_cython + SPKG_INSTALL_REQUIRES_gmpy2 + SPKG_INSTALL_REQUIRES_jupyter_core + SPKG_INSTALL_REQUIRES_memory_allocator + SPKG_INSTALL_REQUIRES_numpy + SPKG_INSTALL_REQUIRES_pkgconfig + SPKG_INSTALL_REQUIRES_pplpy +] +build-backend = "mesonpy" + +[project] +name = "sagemath-standard" +description = "Sage: Open Source Mathematics Software: Standard Python Library" +dependencies = [ + SPKG_INSTALL_REQUIRES_sage_conf + SPKG_INSTALL_REQUIRES_six +dnl From build/pkgs/sagelib/dependencies + SPKG_INSTALL_REQUIRES_conway_polynomials + SPKG_INSTALL_REQUIRES_cypari + SPKG_INSTALL_REQUIRES_cysignals + SPKG_INSTALL_REQUIRES_cython + SPKG_INSTALL_REQUIRES_gmpy2 + SPKG_INSTALL_REQUIRES_importlib_metadata + SPKG_INSTALL_REQUIRES_importlib_resources + SPKG_INSTALL_REQUIRES_jupyter_core + SPKG_INSTALL_REQUIRES_lrcalc_python + SPKG_INSTALL_REQUIRES_memory_allocator + SPKG_INSTALL_REQUIRES_numpy + SPKG_INSTALL_REQUIRES_pkgconfig + SPKG_INSTALL_REQUIRES_pplpy + SPKG_INSTALL_REQUIRES_primecountpy + SPKG_INSTALL_REQUIRES_requests + SPKG_INSTALL_REQUIRES_typing_extensions +dnl From Makefile.in: SAGERUNTIME + SPKG_INSTALL_REQUIRES_ipython + SPKG_INSTALL_REQUIRES_pexpect +dnl From Makefile.in: DOC_DEPENDENCIES + SPKG_INSTALL_REQUIRES_sphinx + SPKG_INSTALL_REQUIRES_networkx + SPKG_INSTALL_REQUIRES_scipy + SPKG_INSTALL_REQUIRES_sympy + SPKG_INSTALL_REQUIRES_matplotlib + SPKG_INSTALL_REQUIRES_pillow + SPKG_INSTALL_REQUIRES_mpmath + SPKG_INSTALL_REQUIRES_ipykernel + SPKG_INSTALL_REQUIRES_jupyter_client + SPKG_INSTALL_REQUIRES_ipywidgets + SPKG_INSTALL_REQUIRES_fpylll +dnl pycryptosat # Sage distribution installs it as part of cryptominisat. According to its README on https://pypi.org/project/pycryptosat/: "The pycryptosat python package compiles while compiling CryptoMiniSat. It cannot be compiled on its own, it must be compiled at the same time as CryptoMiniSat." +dnl Packages with important upper version bounds + SPKG_INSTALL_REQUIRES_ptyprocess +] +dynamic = ["version"] +include(`pyproject_toml_metadata.m4')dnl' + +[project.optional-dependencies] +R = [ + SPKG_INSTALL_REQUIRES_rpy2 +] + +[project.readme] +file = "README.rst" +content-type = "text/x-rst" + +[tool.conda-lock] +platforms = [ + 'osx-64', 'linux-64', 'linux-aarch64', 'osx-arm64' +] + +[tool.setuptools] +script-files = [ + # The sage script + "bin/sage", + # Other scripts that should be in the path also for OS packaging of sage: + "bin/sage-eval", + # Included because it is useful for doctesting/coverage testing user scripts too: + "bin/sage-runtests", + "bin/sage-fixdoctests", + "bin/sage-coverage", + # The following is deprecated but might still be used in user package install scripts + "bin/sage-cython", + # Helper scripts invoked by sage script + # (they would actually belong to something like libexec) + "bin/sage-cachegrind", + "bin/sage-callgrind", + "bin/sage-massif", + "bin/sage-omega", + "bin/sage-valgrind", + "bin/sage-venv-config", + "bin/sage-version.sh", + "bin/sage-cleaner", + # Only makes sense in sage-the-distribution. TODO: Move to another installation script. + "bin/sage-list-packages", + # Uncategorized scripts in alphabetical order + "bin/math-readline", + "bin/sage-env", + # sage-env-config -- installed by sage_conf + # sage-env-config.in -- not to be installed + "bin/sage-grep", + "bin/sage-grepdoc", + "bin/sage-inline-fortran", + "bin/sage-ipynb2rst", + "bin/sage-ipython", + "bin/sage-notebook", + "bin/sage-num-threads.py", + "bin/sage-preparse", + "bin/sage-python", + "bin/sage-run", + "bin/sage-run-cython", + "bin/sage-startuptime.py", + "bin/sage-update-version", +] +license-files = ["LICENSE.txt"] +include-package-data = false + +[tool.setuptools.package-data] +"sage.libs.gap" = ["sage.gaprc"] +"sage.interfaces" = ["sage-maxima.lisp"] +"sage.doctest" = ["tests/*"] +"sage.repl.rich_output" = ["example*"] +sage = [ + "ext_data/*", + "ext_data/kenzo/*", + "ext_data/singular/*", + "ext_data/singular/function_field/*", + "ext_data/images/*", + "ext_data/doctest/*", + "ext_data/doctest/invalid/*", + "ext_data/gap/*", + "ext_data/gap/joyner/*", + "ext_data/mwrank/*", + "ext_data/notebook-ipython/*", + "ext_data/nbconvert/*", + "ext_data/graphs/*", + "ext_data/pari/*", + "ext_data/pari/dokchitser/*", + "ext_data/pari/buzzard/*", + "ext_data/pari/simon/*", + "ext_data/magma/*", + "ext_data/magma/latex/*", + "ext_data/magma/sage/*", + "ext_data/valgrind/*", + "ext_data/threejs/*", +] + +[tool.setuptools.dynamic] +version = {file = ["VERSION.txt"]} From 0f0828caaefed59fb19403fbf7e83aa22db54cbc Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 5 Jan 2024 17:12:44 -0800 Subject: [PATCH 28/30] pkgs/sagemath-{categories,objects,standard}: Use sage-cython-native-file.ini --- build/pkgs/sagelib/spkg-install.in | 4 ++-- build/pkgs/sagemath_objects/spkg-install.in | 3 ++- pkgs/sagemath-categories/sage-cython-native-file.ini | 1 + pkgs/sagemath-objects/sage-cython-native-file.ini | 2 ++ pkgs/sagemath-standard/sage-cython-native-file.ini | 1 + 5 files changed, 8 insertions(+), 3 deletions(-) create mode 120000 pkgs/sagemath-categories/sage-cython-native-file.ini create mode 100644 pkgs/sagemath-objects/sage-cython-native-file.ini create mode 120000 pkgs/sagemath-standard/sage-cython-native-file.ini diff --git a/build/pkgs/sagelib/spkg-install.in b/build/pkgs/sagelib/spkg-install.in index c67e5c28a72..cd06da3be33 100644 --- a/build/pkgs/sagelib/spkg-install.in +++ b/build/pkgs/sagelib/spkg-install.in @@ -64,7 +64,7 @@ if [ "$SAGE_EDITABLE" = yes ]; then if [ "$SAGE_WHEELS" = yes ]; then # Additionally build a wheel (for use in other venvs) - cd $SAGE_PKGS/sagelib/src && time python3 -m build --no-isolation --wheel --skip-dependency-check . && sdh_store_wheel . + cd $SAGE_PKGS/sagelib/src && time python3 -m build --no-isolation --wheel --skip-dependency-check -Csetup-args="--native-file=$(pwd)/sage-cython-native-file.ini" . && sdh_store_wheel . fi else # Make sure that an installed old version of sagelib in which sage is an ordinary package @@ -76,7 +76,7 @@ else if [ "$SAGE_WHEELS" = yes ]; then # Use --no-build-isolation to avoid rebuilds because of dependencies: # Compiling sage/interfaces/sagespawn.pyx because it depends on /private/var/folders/38/wnh4gf1552g_crsjnv2vmmww0000gp/T/pip-build-env-609n5985/overlay/lib/python3.10/site-packages/Cython/Includes/posix/unistd.pxd - time sdh_pip_install --no-build-isolation . + time sdh_pip_install --no-build-isolation -Csetup-args="--native-file=$(pwd)/sage-cython-native-file.ini" . else SAGE_OPTIONAL_PACKAGES_WITH_EXTENSIONS+="mcqd,tdlib,coxeter3,sirocco,meataxe,bliss" time python3 -u setup.py --no-user-cfg build install || exit 1 diff --git a/build/pkgs/sagemath_objects/spkg-install.in b/build/pkgs/sagemath_objects/spkg-install.in index a9b03e706d9..4b687e6b3fe 100644 --- a/build/pkgs/sagemath_objects/spkg-install.in +++ b/build/pkgs/sagemath_objects/spkg-install.in @@ -5,12 +5,13 @@ export CXX=$(echo "$CXX" | sed 's/-std=[a-z0-9+]*//g') export CYTHON=sage-cython export CYTHON_FOR_BUILD=sage-cython + export PIP_NO_INDEX=true export PIP_FIND_LINKS="file://$SAGE_SPKG_WHEELS" # Do not install the wheel. DIST_DIR="$(mktemp -d)" -python3 -m build --no-isolation --wheel --skip-dependency-check --outdir "$DIST_DIR"/dist . || sdh_die "Failure building sdist and wheel" +python3 -m build --no-isolation --wheel --skip-dependency-check -Csetup-args="--native-file=$(pwd)/sage-cython-native-file.ini" --outdir "$DIST_DIR"/dist . || sdh_die "Failure building sdist and wheel" wheel=$(cd "$DIST_DIR" && sdh_store_wheel . >&2 && echo $wheel) ls -l "$wheel" diff --git a/pkgs/sagemath-categories/sage-cython-native-file.ini b/pkgs/sagemath-categories/sage-cython-native-file.ini new file mode 120000 index 00000000000..e9a14ce871a --- /dev/null +++ b/pkgs/sagemath-categories/sage-cython-native-file.ini @@ -0,0 +1 @@ +../sagemath-objects/sage-cython-native-file.ini \ No newline at end of file diff --git a/pkgs/sagemath-objects/sage-cython-native-file.ini b/pkgs/sagemath-objects/sage-cython-native-file.ini new file mode 100644 index 00000000000..3abc0954517 --- /dev/null +++ b/pkgs/sagemath-objects/sage-cython-native-file.ini @@ -0,0 +1,2 @@ +[binaries] +cython = 'sage-cython' diff --git a/pkgs/sagemath-standard/sage-cython-native-file.ini b/pkgs/sagemath-standard/sage-cython-native-file.ini new file mode 120000 index 00000000000..e9a14ce871a --- /dev/null +++ b/pkgs/sagemath-standard/sage-cython-native-file.ini @@ -0,0 +1 @@ +../sagemath-objects/sage-cython-native-file.ini \ No newline at end of file From b8a1f20749002de5188fb07b666bfa69d101e30e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 5 Jan 2024 21:34:41 -0800 Subject: [PATCH 29/30] pkgs/sagemath-standard/pyproject-monolithic.toml: Fix up --- .gitignore | 2 +- pkgs/sagemath-standard/pyproject-monolithic.toml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 120000 pkgs/sagemath-standard/pyproject-monolithic.toml diff --git a/.gitignore b/.gitignore index 6d58fac0d3d..efad460e373 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,7 @@ /src/pyproject.toml /src/Pipfile /src/Pipfile.lock +/src/pyproject.toml /Pipfile /Pipfile.lock @@ -234,7 +235,6 @@ build/bin/sage-build-env-config /pkgs/sagemath-environment/requirements.txt /pkgs/sagemath-repl/requirements.txt /pkgs/sagemath-categories/MANIFEST.in -/pkgs/sagemath-standard/pyproject-monolithic.toml # same for old locations - before Issue #31577 /build/pkgs/*/src/build diff --git a/pkgs/sagemath-standard/pyproject-monolithic.toml b/pkgs/sagemath-standard/pyproject-monolithic.toml new file mode 120000 index 00000000000..ef15d0eea45 --- /dev/null +++ b/pkgs/sagemath-standard/pyproject-monolithic.toml @@ -0,0 +1 @@ +../../src/pyproject.toml \ No newline at end of file From bede1a8ada06adb3bccc5ee6c7adf9840f30cefc Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 5 Jan 2024 23:01:54 -0800 Subject: [PATCH 30/30] build/pkgs/sagemath_objects/spkg-install.in: Move the std flags to CXXFLAGS --- build/pkgs/sagemath_objects/spkg-install.in | 1 + 1 file changed, 1 insertion(+) diff --git a/build/pkgs/sagemath_objects/spkg-install.in b/build/pkgs/sagemath_objects/spkg-install.in index 4b687e6b3fe..c865d91d98e 100644 --- a/build/pkgs/sagemath_objects/spkg-install.in +++ b/build/pkgs/sagemath_objects/spkg-install.in @@ -1,6 +1,7 @@ cd src # For meson +export CXXFLAGS="$CXXFLAGS $(echo "$CXX" | sed -En "s/.*(-std=[a-z0-9+]*).*/\1/p")" export CXX=$(echo "$CXX" | sed 's/-std=[a-z0-9+]*//g') export CYTHON=sage-cython export CYTHON_FOR_BUILD=sage-cython