diff --git a/Makefile b/Makefile index b7303134a3a..06a87e8f265 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ SAGE_ROOT_LOGS = logs # CONFIG_FILES lists all files that appear in AC_CONFIG_FILES in configure.ac; # except for build/make/Makefile-auto, which is unused by the build system -CONFIG_FILES = build/make/Makefile src/bin/sage-env-config build/bin/sage-build-env-config +CONFIG_FILES = build/make/Makefile src/bin/sage-env-config build/bin/sage-build-env-config pkgs/sage-conf/_sage_conf/_conf.py # SPKG_COLLECT_FILES contains the files that influence the *runtime* of the # portions of the 'configure' script generated by the SAGE_SPKG_COLLECT macro diff --git a/configure.ac b/configure.ac index 0c0976e6d66..f147b79bd98 100644 --- a/configure.ac +++ b/configure.ac @@ -581,6 +581,8 @@ AC_SUBST(SAGE_PKG_CONFIG_PATH, [$SAGE_DARWIN_PKG_CONFIG_PATH'$SAGE_LOCAL/lib/pkg AC_CONFIG_FILES([build/make/Makefile-auto build/make/Makefile]) AC_CONFIG_FILES([src/bin/sage-env-config src/bin/sage-src-env-config build/bin/sage-build-env-config]) +AC_CONFIG_FILES([pkgs/sage-conf/_sage_conf/_conf.py]) + dnl Create basic directories needed for Sage AC_CONFIG_COMMANDS(mkdirs, [ diff --git a/configure_wrapper b/configure_wrapper index 4ba1fea55ff..3eb3eeb00b4 100755 --- a/configure_wrapper +++ b/configure_wrapper @@ -1,6 +1,4 @@ #! /bin/sh cp conftest.py bak_conftest.py ./real_configure $@ -realconf_result=$? mv bak_conftest.py conftest.py -exit $realconf_result diff --git a/meson.build b/meson.build index 9c3a9a7f09e..e470de6ab1f 100755 --- a/meson.build +++ b/meson.build @@ -217,6 +217,5 @@ for path in file_paths: run_command(create_files_command, check: true) root = meson.current_source_dir() -root_build = meson.current_build_dir() subdir('src') diff --git a/pkgs/sage-conf/_sage_conf/_conf.py.in b/pkgs/sage-conf/_sage_conf/_conf.py.in new file mode 100644 index 00000000000..eb45225eee4 --- /dev/null +++ b/pkgs/sage-conf/_sage_conf/_conf.py.in @@ -0,0 +1,69 @@ +# @configure_input@ + +VERSION = "@PACKAGE_VERSION@" + +# The following must not be used during build to determine source or installation +# location of sagelib. See comments in SAGE_ROOT/src/Makefile.in +# These variables come first so that other substituted variable values can refer +# to it. +SAGE_LOCAL = "@prefix@" +SAGE_ROOT = "@SAGE_ROOT@" +SAGE_SHARE = "@SAGE_SHARE@" + +# The semicolon-separated list of GAP root paths. This is the list of +# locations that are searched for GAP packages. This is passed directly +# to GAP via the -l flag. +GAP_ROOT_PATHS = "@GAP_ROOT_PATHS@".replace('${prefix}', SAGE_LOCAL) + +# The path to the standalone maxima executable. +MAXIMA = "@SAGE_MAXIMA@".replace('${prefix}', SAGE_LOCAL) + +# Set this to the empty string if your ECL can load maxima without +# further prodding. +MAXIMA_FAS = "@SAGE_MAXIMA_FAS@".replace('${prefix}', SAGE_LOCAL) +MAXIMA_SHARE = "@SAGE_MAXIMA_SHARE@".replace('${prefix}', SAGE_LOCAL) + +# Delete this line if your ECL can load Kenzo without further prodding. +KENZO_FAS = "@SAGE_KENZO_FAS@".replace('${prefix}', SAGE_LOCAL) + +NTL_INCDIR = "@NTL_INCDIR@" +NTL_LIBDIR = "@NTL_LIBDIR@" + +# Path to the ecl-config script +ECL_CONFIG = "@SAGE_ECL_CONFIG@".replace('${prefix}', SAGE_LOCAL) + +SAGE_NAUTY_BINS_PREFIX = "@SAGE_NAUTY_BINS_PREFIX@" + +SAGE_ECMBIN = "@SAGE_ECMBIN@" + +# Names or paths of the 4ti2 executables +FOURTITWO_HILBERT = "@FOURTITWO_HILBERT@" +FOURTITWO_MARKOV = "@FOURTITWO_MARKOV@" +FOURTITWO_GRAVER = "@FOURTITWO_GRAVER@" +FOURTITWO_ZSOLVE = "@FOURTITWO_ZSOLVE@" +FOURTITWO_QSOLVE = "@FOURTITWO_QSOLVE@" +FOURTITWO_RAYS = "@FOURTITWO_RAYS@" +FOURTITWO_PPI = "@FOURTITWO_PPI@" +FOURTITWO_CIRCUITS = "@FOURTITWO_CIRCUITS@" +FOURTITWO_GROEBNER = "@FOURTITWO_GROEBNER@" + +# Colon-separated list of pkg-config modules to search for cblas functionality. +# We hard-code it here as cblas because configure (build/pkgs/openblas/spkg-configure.m4) +# always provides cblas.pc, if necessary by creating a facade pc file for a system BLAS. +CBLAS_PC_MODULES = "cblas" + +# for sage_setup.setenv +SAGE_ARCHFLAGS = "@SAGE_ARCHFLAGS@" +SAGE_PKG_CONFIG_PATH = "@SAGE_PKG_CONFIG_PATH@".replace('$SAGE_LOCAL', SAGE_LOCAL) + +# Used in sage.repl.ipython_kernel.install +MATHJAX_DIR = "@SAGE_MATHJAX_DIR@".replace('${prefix}', SAGE_LOCAL) +THREEJS_DIR = SAGE_LOCAL + "/share/threejs-sage" + +# OpenMP flags, if available. +OPENMP_CFLAGS = "@OPENMP_CFLAGS@" +OPENMP_CXXFLAGS = "@OPENMP_CXXFLAGS@" + +# Installation location of wheels. This is determined at configuration time +# and does not depend on the installation location of sage-conf. +SAGE_SPKG_WHEELS = "@SAGE_VENV@".replace('${SAGE_LOCAL}', SAGE_LOCAL) + "/var/lib/sage/wheels" diff --git a/src/sage/config.py.in b/src/sage/config.py.in deleted file mode 100644 index 993fcbab7e8..00000000000 --- a/src/sage/config.py.in +++ /dev/null @@ -1,149 +0,0 @@ -# @configure_input@ -from pathlib import Path - -import sage - -VERSION = "@PACKAGE_VERSION@" - -# The following must not be used during build to determine source or installation -# location of sagelib. See comments in SAGE_ROOT/src/Makefile.in -# These variables come first so that other substituted variable values can refer -# to it. -SAGE_LOCAL = "@prefix@" -SAGE_ROOT = "@SAGE_ROOT@" -SAGE_SHARE = "@SAGE_SHARE@" - -# The semicolon-separated list of GAP root paths. This is the list of -# locations that are searched for GAP packages. This is passed directly -# to GAP via the -l flag. -GAP_ROOT_PATHS = "@GAP_ROOT_PATHS@".replace("${prefix}", SAGE_LOCAL) - -# The path to the standalone maxima executable. -MAXIMA = "@SAGE_MAXIMA@".replace("${prefix}", SAGE_LOCAL) - -# Set this to the empty string if your ECL can load maxima without -# further prodding. -MAXIMA_FAS = "@SAGE_MAXIMA_FAS@".replace("${prefix}", SAGE_LOCAL) -MAXIMA_SHARE = "@SAGE_MAXIMA_SHARE@".replace("${prefix}", SAGE_LOCAL) - -# Delete this line if your ECL can load Kenzo without further prodding. -KENZO_FAS = "@SAGE_KENZO_FAS@".replace("${prefix}", SAGE_LOCAL) - -NTL_INCDIR = "@NTL_INCDIR@" -NTL_LIBDIR = "@NTL_LIBDIR@" - -# Path to the ecl-config script -ECL_CONFIG = "@SAGE_ECL_CONFIG@".replace("${prefix}", SAGE_LOCAL) - -SAGE_NAUTY_BINS_PREFIX = "@SAGE_NAUTY_BINS_PREFIX@" - -SAGE_ECMBIN = "@SAGE_ECMBIN@" - -# Names or paths of the 4ti2 executables -FOURTITWO_HILBERT = "@FOURTITWO_HILBERT@" -FOURTITWO_MARKOV = "@FOURTITWO_MARKOV@" -FOURTITWO_GRAVER = "@FOURTITWO_GRAVER@" -FOURTITWO_ZSOLVE = "@FOURTITWO_ZSOLVE@" -FOURTITWO_QSOLVE = "@FOURTITWO_QSOLVE@" -FOURTITWO_RAYS = "@FOURTITWO_RAYS@" -FOURTITWO_PPI = "@FOURTITWO_PPI@" -FOURTITWO_CIRCUITS = "@FOURTITWO_CIRCUITS@" -FOURTITWO_GROEBNER = "@FOURTITWO_GROEBNER@" - -# Colon-separated list of pkg-config modules to search for cblas functionality. -# We hard-code it here as cblas because configure (build/pkgs/openblas/spkg-configure.m4) -# always provides cblas.pc, if necessary by creating a facade pc file for a system BLAS. -CBLAS_PC_MODULES = "cblas" - -# for sage_setup.setenv -SAGE_ARCHFLAGS = "@SAGE_ARCHFLAGS@" -SAGE_PKG_CONFIG_PATH = "@SAGE_PKG_CONFIG_PATH@".replace("$SAGE_LOCAL", SAGE_LOCAL) - -# Used in sage.repl.ipython_kernel.install -MATHJAX_DIR = "@SAGE_MATHJAX_DIR@".replace("${prefix}", SAGE_LOCAL) -THREEJS_DIR = SAGE_LOCAL + "/share/threejs-sage" - -# OpenMP flags, if available. -OPENMP_CFLAGS = "@OPENMP_CFLAGS@" -OPENMP_CXXFLAGS = "@OPENMP_CXXFLAGS@" - -# Installation location of wheels. This is determined at configuration time -# and does not depend on the installation location of sage-conf. -SAGE_SPKG_WHEELS = ( - "@SAGE_VENV@".replace("${SAGE_LOCAL}", SAGE_LOCAL) + "/var/lib/sage/wheels" -) - - -def is_editable_install() -> bool: - """ - Check whether this is an editable install of Sage. - - EXAMPLES:: - - sage: from sage.config import is_editable_install - sage: is_editable_install() - False - """ - # This function relies on the fact that meson-python sets up a custom - # loader for editable installs - # Alternatively, one could use the distribution metadata as in: - # https://github.com/scientific-python/spin/blob/89e581c7201d0f6597ffc92c3e84894f99fc133b/spin/cmds/meson.py#L39 - return type(sage.__loader__).__module__ == "_sagemath_editable_loader" - - -def get_editable_root() -> tuple[Path, Path] | None: - """ - Return the path to the Sage directory when using an editable - install. - Both the actual source directory and the build directory are returned, and are - guaranteed to exist. - If not using an editable install, or if the source/build directories do not - exist, return None. - - EXAMPLES:: - - sage: from sage.config import get_editable_root - sage: get_editable_root() - (WindowsPath('/sage'), WindowsPath('/sage/build/cp312')) - """ - if ( - not is_editable_install() - or r"@EDITABLE_SRC@" == "" - or r"@EDITABLE_BUILD@" == "" - ): - return None - - src = Path(r"@EDITABLE_SRC@").resolve() - build = Path(r"@EDITABLE_BUILD@").resolve() - if src.is_dir() and build.is_dir(): - return src, build - return None - - -def get_include_dirs() -> list[Path]: - """ - Return a list of directories to be used as include directories - when compiling Cython extensions that depend on Sage. - - Headers should be included with the prefix "sage/", e.g., - ``#include ``. - - EXAMPLES:: - - sage: from sage.config import get_include_dirs - sage: dirs = get_include_dirs() - sage: dirs # random - [ - WindowsPath('/site-packages'), - WindowsPath('/src'), - WindowsPath('/build/cp312/src'), - WindowsPath('/site-packages/numpy/core/include') - ] - """ - dirs: list[Path] = [Path(dir).parent for dir in sage.__path__] - editable_root = get_editable_root() - if editable_root is not None: - # We return both the source and build directory, - # because some headers are generated in the build directory. - dirs.extend([root / "src" for root in editable_root]) - return [dir for dir in dirs if dir.is_dir()] diff --git a/src/sage/config_test.py b/src/sage/config_test.py deleted file mode 100644 index 6b2512c5ba8..00000000000 --- a/src/sage/config_test.py +++ /dev/null @@ -1,14 +0,0 @@ -from sage.config import get_include_dirs - - -def test_cython_metaclass_header_found(): - dirs = get_include_dirs() - assert any( - (dir / "sage" / "cpython" / "cython_metaclass.h").is_file() for dir in dirs - ) - - -def test_get_include_dirs_returns_existing_dirs(): - dirs = get_include_dirs() - for dir in dirs: - assert dir.is_dir(), f"Directory {dir} does not exist" diff --git a/src/sage/env.py b/src/sage/env.py index 2e41399d871..d8ca93d398f 100644 --- a/src/sage/env.py +++ b/src/sage/env.py @@ -49,7 +49,6 @@ from platformdirs import site_data_dir, user_data_dir from sage import version -from sage.config import get_include_dirs # All variables set by var() appear in this SAGE_ENV dict SAGE_ENV = dict() @@ -308,9 +307,6 @@ def sage_include_directories(use_sources=False): sage: import sage.env sage: sage.env.sage_include_directories() - doctest:warning... - DeprecationWarning: use sage.config.get_include_dirs() instead - ... ['...', '.../numpy/...core/include', '.../include/python...'] @@ -331,9 +327,6 @@ def sage_include_directories(use_sources=False): sage: any(os.path.isfile(os.path.join(d, file)) for d in dirs) True """ - from sage.misc.superseded import deprecation - deprecation(40765, 'use sage.config.get_include_dirs() instead') - if use_sources: dirs = [SAGE_SRC] else: @@ -348,8 +341,6 @@ def sage_include_directories(use_sources=False): dirs.append(sysconfig.get_config_var('INCLUDEPY')) - dirs.extend([dir.as_posix() for dir in get_include_dirs()]) - return dirs diff --git a/src/sage/features/meson_editable.py b/src/sage/features/meson_editable.py index 9bc9eddf987..2fdd59ad420 100644 --- a/src/sage/features/meson_editable.py +++ b/src/sage/features/meson_editable.py @@ -1,8 +1,6 @@ r""" Feature for testing if Meson editable install is used. """ -from sage.config import is_editable_install - from . import Feature, FeatureTestResult @@ -37,7 +35,9 @@ def _is_present(self): sage: MesonEditable()._is_present() # random FeatureTestResult('meson_editable', True) """ - return FeatureTestResult(self, is_editable_install()) + import sage + result = type(sage.__loader__).__module__ == '_sagemath_editable_loader' + return FeatureTestResult(self, result) def all_features(): diff --git a/src/sage/meson.build b/src/sage/meson.build index f422ebc70df..8e2ee496123 100644 --- a/src/sage/meson.build +++ b/src/sage/meson.build @@ -2,8 +2,6 @@ sage_install_dir = py.get_install_dir() / 'sage' # Generate the configuration file conf_data = configuration_data() -conf_data.set('EDITABLE_SRC', root) -conf_data.set('EDITABLE_BUILD', root_build) conf_data.set('PACKAGE_VERSION', '1.2.3') # We use Python's prefix here to make it work with conda prefix = fs.as_posix(py.get_variable('prefix', '')) @@ -85,7 +83,6 @@ py.install_sources( '__init__.py', 'all.py', 'all_cmdline.py', - 'config_test.py', 'env.py', 'version.py', subdir: 'sage', @@ -150,7 +147,7 @@ configure_file( # Write config file # Should be last so that subdir calls can modify the config data config_file = configure_file( - input: 'config.py.in', + input: '../../pkgs/sage-conf/_sage_conf/_conf.py.in', output: 'config.py', install_dir: sage_install_dir, install: true, diff --git a/src/sage/misc/cython.py b/src/sage/misc/cython.py index 5c2b53217a2..97fefe595f3 100644 --- a/src/sage/misc/cython.py +++ b/src/sage/misc/cython.py @@ -27,8 +27,7 @@ import webbrowser from pathlib import Path -from sage.config import get_include_dirs -from sage.env import SAGE_LOCAL, cython_aliases +from sage.env import SAGE_LOCAL, SAGE_SRC, cython_aliases, sage_include_directories from sage.misc.cachefunc import cached_function from sage.misc.sage_ostools import redirection, restore_cwd from sage.misc.temporary_file import spyx_tmp, tmp_filename @@ -59,7 +58,7 @@ def _standard_libs_libdirs_incdirs_aliases(): if SAGE_LOCAL: standard_libdirs.append(os.path.join(SAGE_LOCAL, "lib")) standard_libdirs.extend(aliases["CBLAS_LIBDIR"] + aliases["NTL_LIBDIR"]) - standard_incdirs = [dir.as_posix() for dir in get_include_dirs()] + aliases["CBLAS_INCDIR"] + aliases["NTL_INCDIR"] + standard_incdirs = sage_include_directories(use_sources=True) + [SAGE_SRC] + aliases["CBLAS_INCDIR"] + aliases["NTL_INCDIR"] return standard_libs, standard_libdirs, standard_incdirs, aliases ################################################################