sagemath/sage

./configure: Make --with-sage-venv=auto the default

mkoeppe opened this issue · 79 comments

Since Sage 9.4, it is possible to use an installation tree for Python packages separate from SAGE_LOCAL:
https://wiki.sagemath.org/ReleaseTours/sage-9.4#For_developers:_..2Fconfigure_--prefix.3DSAGE_LOCAL_--with-sage-venv.3DSAGE_VENV

In this ticket we make a new setting --with-sage-venv=auto the default, which means:

  • if --prefix has not been used (so SAGE_LOCAL=local), then set SAGE_VENV to local/var/lib/sage/venv-PYTHONVERSION
    Users can also pass --with-sage-venv or --with-sage-venv=yes, which means to unconditionally set SAGE_VENV to SAGE_LOCAL/var/lib/sage/venv-PYTHONVERSION.

(We keep the layout as is in incremental builds.)

By keying the default name to the Python version, we ensure that if the system python version changes (either because of system updates or explicit reconfiguration), we create a fresh venv and automatically rebuild all Python packages, eliminating problems such as the one reported in https://groups.google.com/g/sage-devel/c/hZPHxqn_Cyk/m/fOAZCUWHAQAJ

Moreover, at config.status time, we create a symbolic link SAGE_ROOT/venv -> SAGE_VENV (overwriting an existing symbolic link)

The link is for easy access by users and is not used otherwise. Instead of local/lib/python3/site-packages/ or local/bin/sage, use venv/local/lib/python3/site-packages/ etc.

For symmetry, we also create a symbolic link SAGE_ROOT/prefix -> SAGE_LOCAL. (This generalizes what is already done by tox local.)

Users will still be able to restore the previous behavior by using --with-sage-venv=no, or use a specific path as in --with-sage-venv=/path/to/venv.

CC: @dimpase @jhpalmieri

Component: build: configure

Author: Matthias Koeppe

Reviewer: John Palmieri

Issue created by migration from https://trac.sagemath.org/ticket/32442

Changed dependencies from #32286, #32387 to #32386, #32387

Description changed:

--- 
+++ 
@@ -1,16 +1,18 @@
 Since Sage 9.4, it is possible to use an installation tree for Python packages separate from SAGE_LOCAL:
 https://wiki.sagemath.org/ReleaseTours/sage-9.4#For_developers:_..2Fconfigure_--prefix.3DSAGE_LOCAL_--with-sage-venv.3DSAGE_VENV
 
-In this ticket we make `--with-sage-venv[=yes]` the default, which will mean:
-- set `SAGE_VENV` to `SAGE_LOCAL/var/lib/sage/venv-PYTHONVERSION`
+In this ticket we make a new setting `--with-sage-venv=auto` the default, which means: 
+- if `--prefix` has not been used (so `SAGE_LOCAL=local`), then 
+set `SAGE_VENV` to `local/var/lib/sage/venv-PYTHONVERSION`
+Users can also pass `--with-sage-venv` or `--with-sage-venv=yes`, which means to unconditionally set `SAGE_VENV` to `SAGE_LOCAL/var/lib/sage/venv-PYTHONVERSION`.
 
-  By keying the name to the Python version, we ensure that if the system python version changes, we create a fresh venv and automatically rebuild all Python packages, eliminating problems such as the one reported in https://groups.google.com/g/sage-devel/c/hZPHxqn_Cyk/m/fOAZCUWHAQAJ
+By keying the default name to the Python version, we ensure that if the system python version changes (either because of system updates or explicit reconfiguration), we create a fresh venv and automatically rebuild all Python packages, eliminating problems such as the one reported in https://groups.google.com/g/sage-devel/c/hZPHxqn_Cyk/m/fOAZCUWHAQAJ
 
-- at `config.status` time, create a symbolic link `SAGE_ROOT/venv -> SAGE_VENV` (overwriting an existing symbolic link)
+Moreover, at `config.status` time, we create a symbolic link `SAGE_ROOT/venv -> SAGE_VENV` (overwriting an existing symbolic link)
 
-  The link is for easy access by users and is not used otherwise. Instead of `local/lib/python3/site-packages/` or `local/bin/sage`, use `venv/local/lib/python3/site-packages/` etc.
+The link is for easy access by users and is not used otherwise. Instead of `local/lib/python3/site-packages/` or `local/bin/sage`, use `venv/local/lib/python3/site-packages/` etc.
 
-  For symmetry, we also create a symbolic link `SAGE_ROOT/prefix -> SAGE_LOCAL`. (This generalizes what is already done by `tox local`.)
+For symmetry, we also create a symbolic link `SAGE_ROOT/prefix -> SAGE_LOCAL`. (This generalizes what is already done by `tox local`.)
 
 Users will still be able to restore the previous behavior by using `--with-sage-venv=no`, or use a specific path as in `--with-sage-venv=/path/to/venv`.
 

Description changed:

--- 
+++ 
@@ -2,8 +2,7 @@
 https://wiki.sagemath.org/ReleaseTours/sage-9.4#For_developers:_..2Fconfigure_--prefix.3DSAGE_LOCAL_--with-sage-venv.3DSAGE_VENV
 
 In this ticket we make a new setting `--with-sage-venv=auto` the default, which means: 
-- if `--prefix` has not been used (so `SAGE_LOCAL=local`), then 
-set `SAGE_VENV` to `local/var/lib/sage/venv-PYTHONVERSION`
+- if `--prefix` has not been used (so `SAGE_LOCAL=local`), then set `SAGE_VENV` to `local/var/lib/sage/venv-PYTHONVERSION`
 Users can also pass `--with-sage-venv` or `--with-sage-venv=yes`, which means to unconditionally set `SAGE_VENV` to `SAGE_LOCAL/var/lib/sage/venv-PYTHONVERSION`.
 
 By keying the default name to the Python version, we ensure that if the system python version changes (either because of system updates or explicit reconfiguration), we create a fresh venv and automatically rebuild all Python packages, eliminating problems such as the one reported in https://groups.google.com/g/sage-devel/c/hZPHxqn_Cyk/m/fOAZCUWHAQAJ

Commit: f700640

New commits:

2f5be2dconfigure.ac, build/pkgs/python3/spkg-configure.m4: New default --with-sage-venv=auto
f700640configure.ac: In config.status, create convenience symlinks prefix, venv

Author: Matthias Koeppe

Changed commit from f700640 to 12cbbda

Branch pushed to git repo; I updated commit sha1. New commits:

b4a3845m4/sage_spkg_collect.m4: If we install python3 spkg, install it in SAGE_VENV
12cbbdaconfigure.ac: Keep old behavior of SAGE_VENV in incremental builds

Changed commit from 12cbbda to 117fe3a

Branch pushed to git repo; I updated commit sha1. New commits:

117fe3abuild/make/Makefile.in (...-clean): Do not fail trying to uninstall if SAGE_VENV has not been created yet

Description changed:

--- 
+++ 
@@ -4,6 +4,8 @@
 In this ticket we make a new setting `--with-sage-venv=auto` the default, which means: 
 - if `--prefix` has not been used (so `SAGE_LOCAL=local`), then set `SAGE_VENV` to `local/var/lib/sage/venv-PYTHONVERSION`
 Users can also pass `--with-sage-venv` or `--with-sage-venv=yes`, which means to unconditionally set `SAGE_VENV` to `SAGE_LOCAL/var/lib/sage/venv-PYTHONVERSION`.
+
+(We keep the layout as is in incremental builds.)
 
 By keying the default name to the Python version, we ensure that if the system python version changes (either because of system updates or explicit reconfiguration), we create a fresh venv and automatically rebuild all Python packages, eliminating problems such as the one reported in https://groups.google.com/g/sage-devel/c/hZPHxqn_Cyk/m/fOAZCUWHAQAJ
 

Changed dependencies from #32386, #32387 to none

Changed commit from 117fe3a to 8af6041

Branch pushed to git repo; I updated commit sha1. New commits:

8af6041Merge tag '9.5.beta2' into t/32442/__configure__make___with_sage_venv_the_default
comment:11

After running make distclean && ./configure:

% git status
On branch t/32442/__configure__make___with_sage_venv_the_default
Your branch is up to date with 'trac/u/mkoeppe/__configure__make___with_sage_venv_the_default'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	venv

nothing added to commit but untracked files present (use "git add" to track)
comment:12

Oh, and venv is a symlink pointing to local.

Changed commit from 8af6041 to b3f7d34

Branch pushed to git repo; I updated commit sha1. New commits:

b3f7d34.gitignore: Add /venv
comment:14

Thanks for catching this!

comment:15

Replying to @jhpalmieri:

Oh, and venv is a symlink pointing to local.

Yes, in an incremental build, nothing should change (except that this symlink is created).

After a make distclean, the new behavior will show

comment:16

Oh, now I see that you said you did make distclean...

comment:17

Maybe this has been going on with venv builds for a while, but the symlinks look messed up to me: my local directory looks like

% ls -l local
total 0
drwxr-xr-x  148 jpalmier  staff  4736 Sep 27 16:21 bin
drwxr-xr-x    2 jpalmier  staff    64 Sep 27 16:09 etc
drwxr-xr-x   47 jpalmier  staff  1504 Sep 27 16:21 include
drwxr-xr-x   73 jpalmier  staff  2336 Sep 27 16:44 lib
lrwxr-xr-x    1 jpalmier  staff     3 Sep 27 16:09 lib64 -> lib
drwxr-xr-x    4 jpalmier  staff   128 Sep 27 16:21 libexec
lrwxr-xr-x    1 jpalmier  staff     5 Sep 27 16:09 local -> local
drwxr-xr-x   34 jpalmier  staff  1088 Sep 27 16:21 share
drwxr-xr-x    5 jpalmier  staff   160 Sep 27 16:13 var
lrwxr-xr-x    1 jpalmier  staff    33 Sep 27 16:09 venv-python3.9 -> local/var/lib/sage/venv-python3.9

In particular, local/local points to itself, and so venv-python3.9 doesn't point anywhere. venv-python3.9 should probably point to ../local/..... I don't know what the local symlink is supposed to do.

Everything still builds, so this is obviously not crucial, but it doesn't look right.

comment:18

Yes, that doesn't look right. Could you post config.log please?

Attachment: config.log

comment:19

This was after make distclean && ./configure && make ptestlong.

Changed commit from b3f7d34 to fc4b641

Branch pushed to git repo; I updated commit sha1. New commits:

fc4b641configure.ac: Remove conveniene symlinks before (re)creating them
comment:21

Try with this version please

comment:22

I've started, and I now only see one symlink in local: lib64 -> lib. At the top level, I see prefix -> local and venv -> local/var/lib/sage/venv-python3.9.

By the way, make distclean should probably remove the top-level symlink venv. As it is, running make distclean first runs ./configure (at least some of the time) which creates venv.

comment:23

make distclean should also remove prefix.

comment:24

Replying to @jhpalmieri:

I've started, and I now only see one symlink in local: lib64 -> lib. At the top level, I see prefix -> local and venv -> local/var/lib/sage/venv-python3.9.

Great, this is the intended layout.

Branch pushed to git repo; I updated commit sha1. New commits:

8bcbf1dMakefile (distclean): Remove convenience symlinks prefix, venv

Changed commit from fc4b641 to 8bcbf1d

comment:26

How is it decided which documentation goes in local/share/doc and which goes in venv/share/doc? For example, pplpy and sage are local/share/doc, although their corresponding installation files are in venv/var/lib/sage/installed.

comment:27

I haven't really paid attention to the documentation. There is no attempt to actively install documentation in venv. The installation of the documentation is not really done by these Python packages themselves but rather by our Sage-specific install scripts. build/pkgs/pplpy/spkg-postinst.in directly refers to SAGE_SHARE (= local/share) for the installation location. I'd say a more systematic consideration of this issue would be something for #29868.

comment:28

On the other hand, networkx and sagetex put their docs in the venv location. Not a big deal and we can certainly deal with it on another ticket.

comment:29

Thanks for investigating. These two Python packages install their documentation by themselves on setup.py install (and similar), we are not doing anything Sage-specific there. Perhaps at some point we'll get around to moving #27164 forward...

comment:30

Can you explain the change in Makefile.in? In what circumstances would the package tree directory not exist?

comment:31

I think that ./configure --help should be changed from

  --with-sage-venv={auto,yes,no,SAGE_VENV}

to

  --with-sage-venv={auto (default),yes,no,SAGE_VENV}
comment:32

In this line from configure.ac:

    eval SAGE_VENV="$SAGE_VENV"dnl eval so as to evaluate the embedded ${SAGE_LOCAL}

the placement of dnl... doesn't fit the style of the rest of the file. I honestly don't care. Is there any point to change it?

comment:33

Replying to @jhpalmieri:

Can you explain the change in Makefile.in? In what circumstances would the package tree directory not exist?

Running make SCRIPTPACKAGE-clean or ./sage -f SCRIPTPACKAGE right after running ./configure (or before any package is installed into the venv)

Branch pushed to git repo; I updated commit sha1. New commits:

dcb4a08configure.ac: Indicate default in help string for --with-sage-venv

Changed commit from 8bcbf1d to dcb4a08

comment:35

Replying to @jhpalmieri:

the placement of dnl... doesn't fit the style of the rest of the file. I honestly don't care. Is there any point to change it?

It's correct as is, to suppress unnecessary whitespace in the generated file. There are lots of other places in our autoconf scripts that are not quite so careful about this, in the end it does not matter so much

comment:36

I think this is ready to go, but I will ask one more question — probably not a question for this ticket, just a general venv question: how do I use a venv? I built Sage using homebrew's Python 3.9, and I wanted to see what happened with /usr/bin/python3, which is version 3.8. But just doing ./configure --with-python=/usr/bin/python3 doesn't accomplish anything because local/bin/python3 is still a symlink pointing to homebrew's Python. What do I need to do to convince Sage to use a different Python, therefore creating a different venv, while keeping the other venv? Do I need to manually remove the Python symlink?

comment:37

Replying to @jhpalmieri:

But just doing ./configure --with-python=/usr/bin/python3 doesn't accomplish anything because local/bin/python3 is still a symlink pointing to homebrew's Python.

Try ./configure --with-python=/usr/bin/python3 --with-sage-venv=yes

comment:38

Should --with-sage-venv=auto detect whether this is an incremental build from an earlier build using --with-sage-venv=auto, i.e. whether SAGE_ENV matches local/var/lib/sage/venv-SOMEPYTHONVERSION? And if so, then should it use the appropriate possibly new directory for the venv? Otherwise the ticket description's "we ensure that if the system python version changes (either because of system updates or explicit reconfiguration), we create a fresh venv" is not accurate: this will only happen if the user says --with-sage-venv=yes, if I understand correctly.

comment:39

If you start from a distclean source tree, the default --with-sage-venv=auto does not create a python3 in local/bin/. So it will work as advertised.

I think you are testing with a tree that has python3 in local/bin/, either from a build before this ticket, or from a defective earlier version of this ticket.

comment:40

I think you're right, I think it's working the way it's supposed to. Let me test one or two more things.

comment:41

Can this be fixed? I did

% ./configure   # use homebrew's Python 3.9
% make ptestlong
...
all tests passed
% ./configure --with-python=/usr/bin/python3   # Python 3.8
% make
% ./sage -tp src/sage_setup
...
sage -t --warn-long 107.1 --random-seed=0 src/sage_setup/clean.py  # 1 doctest failed
sage -t --warn-long 107.1 --random-seed=0 src/sage_setup/find.py  # 2 doctests failed

Details:

File "src/sage_setup/clean.py", line 96, in sage_setup.clean._find_stale_files
Failed example:
    for f in stale_iter:
        if f.endswith(skip_extensions): continue
        if '/ext_data/' in f: continue
        print('Found stale file: ' + f)
Expected nothing
Got:
    Found stale file: /Users/palmieri/Library/Caches/com.apple.python/Users/palmieri/Desktop/Sage/sage_builds/TESTING/sage-9.5.beta2/local/var/lib/sage/venv-python3.8/lib/python3.8/site-packages/sage/all_cmdline.cpython-38.pyc
    Found stale file: /Users/palmieri/Library/Caches/com.apple.python/Users/palmieri/Desktop/Sage/sage_builds/TESTING/sage-9.5.beta2/local/var/lib/sage/venv-python3.8/lib/python3.8/site-packages/sage/version.cpython-38.pyc
...
 [many lines like this]

and

File "src/sage_setup/find.py", line 365, in sage_setup.find.installed_files_by_module
Failed example:
    f1
Expected:
    'sage/structure/__init__.py'
Got:
    '/Users/palmieri/Library/Caches/com.apple.python/Users/palmieri/Desktop/Sage/sage_builds/TESTING/sage-9.5.beta2/local/var/lib/sage/venv-python3.8/lib/python3.8/site-packages/sage/structure/__init__.cpython-38.pyc'
**********************************************************************
File "src/sage_setup/find.py", line 367, in sage_setup.find.installed_files_by_module
Failed example:
    f2
Expected:
    'sage/structure/....pyc'
Got:
    'sage/structure/__init__.py'
comment:42

This is #31314

comment:43

Okay, then I think this is ready.

Reviewer: John Palmieri

comment:44

Thank you!

comment:45

Breaks build on Debian 9:

Testing importing of various modules...
ctypes module imported OK
math module imported OK
hashlib module imported OK
crypt module imported OK
socket module imported OK
zlib module imported OK
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/buildbot/slave/sage_git/build/local/var/lib/sage/venv-python3.9.7/var/tmp/sage/build/python3-3.9.7/src/Lib/sqlite3/__init__.py", line 23, in <module>
    from sqlite3.dbapi2 import *
  File "/home/buildbot/slave/sage_git/build/local/var/lib/sage/venv-python3.9.7/var/tmp/sage/build/python3-3.9.7/src/Lib/sqlite3/dbapi2.py", line 27, in <module>
    from _sqlite3 import *
ModuleNotFoundError: No module named '_sqlite3'
sqlite3 module failed to import
ssl module imported OK
Error: One or more modules failed to import.
real	1m25.694s
user	2m0.796s
sys	0m10.188s
************************************************************************
Error building package python3-3.9.7
************************************************************************
comment:46

Build log please

comment:47

I was able to reproduce this using tox -e docker-debian-stretch-minimal.

Changed commit from dcb4a08 to 2101b8c

Branch pushed to git repo; I updated commit sha1. New commits:

e33bc89Merge tag '9.5.beta3' into t/32442/__configure__make___with_sage_venv_the_default
2101b8cbuild/pkgs/python3/spkg-build.in: Make sure that python finds sqlite3 when determining which extension modules to build
comment:50

When I run tox -e docker-debian-stretch-minimal, where are the package log files?

comment:51

They are in the Docker container.
At the end of the build, tox will tell you name and/or sha256 hash of the image built.
You can to docker run -it IMAGE bash to enter the container and then it's all in /sage/logs

comment:52

Okay, before this latest change I see the Python problem, as well as:

* package:         python3-3.9.7
  last build time: Oct 13 17:49
  log file:        /sage/logs/pkgs/python3-3.9.7.log

* package:         fplll-5.4.1
  last build time: Oct 13 18:01
  log file:        /sage/logs/pkgs/fplll-5.4.1.log
  build directory: /sage/local/var/tmp/sage/build/fplll-5.4.1

* package:         cmake-3.21.0
  last build time: Oct 13 18:04
  log file:        /sage/logs/pkgs/cmake-3.21.0.log
  build directory: /sage/local/var/tmp/sage/build/cmake-3.21.0

* package:         gfortran-10.3.0
  last build time: Oct 13 18:14
  log file:        /sage/logs/pkgs/gfortran-10.3.0.log
  build directory: /sage/local/var/tmp/sage/build/gfortran-10.3.0

The other failures appear to be unrelated to this ticket: I get them with the develop branch.

comment:53

Replying to @jhpalmieri:

The other failures appear to be related to this ticket: I get them with the develop branch.

Did you mean to write "unrelated to this ticket"?

comment:54

Yes, sorry, unrelated. I've edited to make it clearer in case anyone looks at this later. With the most recent branch here, Python builds correctly. I think that's good enough for another positive review.

comment:55

Thank you!

By the way, I cannot reproduce the failures with the other packages, and they also built correctly on GH Actions https://github.com/sagemath/sage/runs/3863930628?check_suite_focus=true

comment:56

Maybe the issue was that my Docker was out of date, or maybe it was a memory issue. I upgraded Docker and allocated more RAM to it, and now those packages build.

comment:57

I do get another failure, though; don't know if it's related to this ticket. With tox -e docker-debian-stretch-minimal, I get:

gcc version 6.3.0 20170516 (Debian 6.3.0-18+deb9u1) 
****************************************************
Package 'setuptools' is currently not installed
No legacy uninstaller found for 'setuptools'; nothing to do
python3: error while loading shared libraries: libpython3.9.so.1.0: cannot open shared object file: No such file or directory
********************************************************************************
Error building / installing setuptools for Python
********************************************************************************

real	0m0.021s
user	0m0.011s
sys	0m0.010s
************************************************************************
Error installing package setuptools-58.0.2
************************************************************************
Please email sage-devel (http://groups.google.com/group/sage-devel)
explaining the problem and including the log files
  /sage/logs/pkgs/setuptools-58.0.2.log
and
  /sage/config.log
Describe your computer, operating system, etc.
If you want to try to fix the problem yourself, *don't* just cd to
/sage/local/var/lib/sage/venv-python3.9.7/var/tmp/sage/build/setuptools-58.0.2 and type 'make' or whatever is appropriate.
Instead, the following commands setup all environment variables
correctly and load a subshell for you to debug the error:
  (cd '/sage/local/var/lib/sage/venv-python3.9.7/var/tmp/sage/build/setuptools-58.0.2' && '/sage/sage' --buildsh)
When you are done debugging, you can type "exit" to leave the subshell.
comment:58

There is a file SAGE_ROOT/venv/local/lib/libpython3.9.so.1.0. If I run ./sage --python then I get the same error.

comment:59

Yes, I see this error now too.

comment:61

Looks like on Linux I need to set the linker flags differently.

Changed commit from 2101b8c to 3bbc5d8

Branch pushed to git repo; I updated commit sha1. New commits:

3bbc5d8build/pkgs/python3/spkg-build.in: Set rpath
comment:64

This fixes it for me; this time I ran a complete build

comment:65

This ticket (at 2101b8c) is already on Volker's branch.
I've opened #32698 for the fix.

comment:66

This works for me with a few different builds (standard build on my machine and a few tox builds via Docker).

Changed commit from 3bbc5d8 to none

comment:67

This was merged along with #32698