Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Issues with prefix/destdir and "Broken python installation detected" warnings #82

Closed
ev-br opened this issue Oct 10, 2021 · 42 comments
Closed

Comments

@ev-br
Copy link

ev-br commented Oct 10, 2021

Describe your issue.

Am trying to build the tip of the master branch with meson in a virtualenv on ubuntu focal. The setup works fine for the scipy master with setup.py / runtests.py / pip, but with meson fails with a nonsensical cannot find <complex> hearder in scipy.special.

Here's a full set of steps:

# shallow clone the rgommers/scipy fork:

$ git log
commit 683a74a3a4cd507eaba5c7e92b6ef4d81f2cc178 (grafted, HEAD -> meson, origin/meson, origin/HEAD)
Author: Smit Lunagariya <55887635+Smit-create@users.noreply.github.com>
Date:   Sat Oct 9 16:17:01 2021 +0530

    CI: Fix and Check installation of test files (#81)

### Patch up to use system blas/lapack (should not matter)

$ git diff
diff --git a/scipy/meson.build b/scipy/meson.build
index 6d4931e..aaf8f6c 100644
--- a/scipy/meson.build
+++ b/scipy/meson.build
@@ -72,8 +72,8 @@ numpy_nodepr_api = '-DNPY_NO_DEPRECATED_API=NPY_1_9_API_VERSION'
 
 
 # TODO: 64-bit BLAS and LAPACK
-blas = dependency('openblas')
-lapack = dependency('openblas')
+blas = dependency('blas')
+lapack = dependency('lapack')
 
 # TODO: deal with case where we do need the g77 ABI wrappers (see
 #       _build_utils/_fortran.py)
diff --git a/scipy/odr/meson.build b/scipy/odr/meson.build
index 5c544fa..031539a 100644
--- a/scipy/odr/meson.build
+++ b/scipy/odr/meson.build
@@ -16,7 +16,7 @@ odrpack = static_library('odrpack',
 # conda: pkgconfig.variables('openblas')
 # https://github.com/mesonbuild/meson/issues/2835
 # TODO: 64-bit BLAS
-blas = dependency('openblas')
+blas = dependency('blas')
 
 py3.extension_module('__odrpack',
   '__odrpack.c',

# make a fresh virtualenv

br@gonzales:~/sweethome/temp/meson_scipy/scipy$ mkvirtualenv scipy_meson                       
created virtual environment CPython3.8.10.final.0-64 in 94ms
  creator CPython3Posix(dest=/home/br/.virtualenvs/scipy_meson, clear=False, no_vcs_ignore=False, global=False)
  seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/home/br/.local/share/virtualenv)
    added seed packages: pip==21.2.4, setuptools==58.0.4, wheel==0.37.0
  activators BashActivator,CShellActivator,FishActivator,PowerShellActivator,PythonActivator,XonshActivator
virtualenvwrapper.user_scripts creating /home/br/.virtualenvs/scipy_meson/bin/predeactivate
virtualenvwrapper.user_scripts creating /home/br/.virtualenvs/scipy_meson/bin/postdeactivate
virtualenvwrapper.user_scripts creating /home/br/.virtualenvs/scipy_meson/bin/preactivate
virtualenvwrapper.user_scripts creating /home/br/.virtualenvs/scipy_meson/bin/postactivate
virtualenvwrapper.user_scripts creating /home/br/.virtualenvs/scipy_meson/bin/get_env_details
(scipy_meson) br@gonzales:~/sweethome/temp/meson_scipy/scipy$ pip install --upgrade pip
Requirement already satisfied: pip in /home/br/.virtualenvs/scipy_meson/lib/python3.8/site-packages (21.2.4)
(scipy_meson) br@gonzales:~/sweethome/temp/meson_scipy/scipy$ pip install numpy cython pythran
Collecting numpy
  Using cached numpy-1.21.2-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl (15.8 MB)
Collecting cython
  Using cached Cython-0.29.24-cp38-cp38-manylinux1_x86_64.whl (1.9 MB)
Collecting pythran
  Using cached pythran-0.10.0-py3-none-any.whl (4.3 MB)
Collecting ply>=3.4
  Using cached ply-3.11-py2.py3-none-any.whl (49 kB)
Collecting beniget~=0.4.0
  Using cached beniget-0.4.1-py3-none-any.whl (9.4 kB)
Collecting gast~=0.5.0
  Using cached gast-0.5.2-py3-none-any.whl (10 kB)
Installing collected packages: gast, ply, numpy, beniget, pythran, cython
Successfully installed beniget-0.4.1 cython-0.29.24 gast-0.5.2 numpy-1.21.2 ply-3.11 pythran-0.10.0
(scipy_meson) br@gonzales:~/sweethome/temp/meson_scipy/scipy$ pip install meson ninja
Collecting meson
  Using cached meson-0.59.2-py3-none-any.whl
Collecting ninja
  Using cached ninja-1.10.2.2-py2.py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.whl (108 kB)
Installing collected packages: ninja, meson
Successfully installed meson-0.59.2 ninja-1.10.2.2
(scipy_meson) br@gonzales:~/sweethome/temp/meson_scipy/scipy$ pip install pybind11

#### All deps are there, start building

(scipy_meson) br@gonzales:~/sweethome/temp/meson_scipy/scipy$ rm -rf installdir
(scipy_meson) br@gonzales:~/sweethome/temp/meson_scipy/scipy$ rm -rf builddir
(scipy_meson) br@gonzales:~/sweethome/temp/meson_scipy/scipy$ meson setup builddir --prefix=$PWD/installdir
The Meson build system
Version: 0.59.2
Source dir: /home/br/sweethome/temp/meson_scipy/scipy
Build dir: /home/br/sweethome/temp/meson_scipy/scipy/builddir
Build type: native build
Project name: SciPy
Project version: 1.7.0.dev0+ababababab
C compiler for the host machine: cc (gcc 9.3.0 "cc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0")
C linker for the host machine: cc ld.bfd 2.34
C++ compiler for the host machine: c++ (gcc 9.3.0 "c++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0")
C++ linker for the host machine: c++ ld.bfd 2.34
Cython compiler for the host machine: cython (cython 0.29.24)
Host machine cpu family: x86_64
Host machine cpu: x86_64
Fortran compiler for the host machine: gfortran (gcc 9.3.0 "GNU Fortran (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0")
Fortran linker for the host machine: gfortran ld.bfd 2.34
Program cython found: YES (/home/br/.virtualenvs/scipy_meson/bin/cython)
Program pythran found: YES (/home/br/.virtualenvs/scipy_meson/bin/pythran)
Program python3 found: YES (/home/br/.virtualenvs/scipy_meson/bin/python)
WARNING: Broken python installation detected. Python files installed by Meson might not be found by python interpreter.
Found pkg-config: /usr/bin/pkg-config (0.29.1)
Dependency python found: YES (pkgconfig)
Library npymath found: YES
Library npyrandom found: YES
Run-time dependency blas found: YES 3.9.0
Run-time dependency lapack found: YES 3.9.0
Program cp found: YES (/usr/bin/cp)
Program cp found: YES (/usr/bin/cp)
Checking for function "open_memstream" : NO 
Configuring messagestream_config.h using configuration
Compiler for C++ supports arguments -fvisibility=hidden: YES 
Program cp found: YES (/usr/bin/cp)
Program cp found: YES (/usr/bin/cp)
Program cp found: YES (/usr/bin/cp)
Checking for size of "void*" : 8
Program cp found: YES (/usr/bin/cp)
Run-time dependency threads found: YES
Checking for size of "void*" : 8
Dependency threads found: YES unknown (cached)
Program cp found: YES (/usr/bin/cp)
Compiler for C++ supports arguments -fvisibility=hidden: YES (cached)
Dependency blas found: YES 3.9.0 (cached)
Program cp found: YES (/usr/bin/cp)
Program cp found: YES (/usr/bin/cp)
Build targets in project: 199

Found ninja-1.10.2.git.kitware.jobserver-1 at /home/br/.virtualenvs/scipy_meson/bin/ninja

$ meson install -C builddir
ninja: Entering directory `/home/br/sweethome/temp/meson_scipy/scipy/builddir'
[218/1492] Compiling C object scipy/special/_ufuncs_cxx.cpython-38-...64-linux-gnu.so.p/meson-generated_scipy_special__ufuncs_cxx.pyx.c.o
FAILED: scipy/special/_ufuncs_cxx.cpython-38-x86_64-linux-gnu.so.p/meson-generated_scipy_special__ufuncs_cxx.pyx.c.o 
cc -Iscipy/special/_ufuncs_cxx.cpython-38-x86_64-linux-gnu.so.p -Iscipy/special -I../scipy/special -I/home/br/.virtualenvs/scipy_meson/lib/python3.8/site-packages/numpy/core/include -Iscipy/_lib -I../scipy/_lib -I../scipy/_build_utils/src -Iscipy -I/usr/include/python3.8 -I/usr/include/x86_64-linux-gnu/python3.8 -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -w -std=c99 -O2 -g -Wno-unused-function -Wno-conversion -Wno-unused-but-set-variable -Wno-misleading-indentation -Wno-incompatible-pointer-types -fPIC -MD -MQ scipy/special/_ufuncs_cxx.cpython-38-x86_64-linux-gnu.so.p/meson-generated_scipy_special__ufuncs_cxx.pyx.c.o -MF scipy/special/_ufuncs_cxx.cpython-38-x86_64-linux-gnu.so.p/meson-generated_scipy_special__ufuncs_cxx.pyx.c.o.d -o scipy/special/_ufuncs_cxx.cpython-38-x86_64-linux-gnu.so.p/meson-generated_scipy_special__ufuncs_cxx.pyx.c.o -c scipy/special/_ufuncs_cxx.cpython-38-x86_64-linux-gnu.so.p/scipy/special/_ufuncs_cxx.pyx.c
In file included from /home/br/sweethome/temp/meson_scipy/scipy/builddir/scipy/special/_ufuncs_cxx_defs.h:3,
                 from scipy/special/_ufuncs_cxx.cpython-38-x86_64-linux-gnu.so.p/scipy/special/_ufuncs_cxx.pyx.c:631:
../scipy/special/_faddeeva.h:12:10: fatal error: complex: No such file or directory
   12 | #include <complex>
      |          ^~~~~~~~~
compilation terminated.
[227/1492] Compiling Fortran object scipy/special/libspecfun.a.p/specfun_specfun.f.o
ninja: build stopped: subcommand failed.
Could not rebuild /home/br/sweethome/temp/meson_scipy/scipy/builddir

(scipy_meson) br@gonzales:~/sweethome/temp/meson_scipy/scipy$ ls scipy/special/_fa*
scipy/special/_factorial.pxd  scipy/special/_faddeeva.cxx  scipy/special/_faddeeva.h

Reproducing Code Example

.

Error message

.

SciPy/NumPy/Python version information

.

@rgommers
Copy link
Owner

Using cached meson-0.59.2-py3-none-any.whl

You need Meson master (or https://github.com/rgommers/meson/tree/scipy) for the build to succeed. Could you try that and see if it helps? I'm not sure it will, because I haven't tried virtualenv yet, but 0.59.2 is certainly too old.

@ev-br
Copy link
Author

ev-br commented Oct 10, 2021

Yup, that was it!

With

$ pip uninstall meson
Found existing installation: meson 0.59.2
Uninstalling meson-0.59.2:
  Would remove:
    /home/br/.virtualenvs/scipy_meson/bin/meson
    /home/br/.virtualenvs/scipy_meson/lib/python3.8/site-packages/meson-0.59.2.dist-info/*
    /home/br/.virtualenvs/scipy_meson/lib/python3.8/site-packages/mesonbuild/*
    /home/br/.virtualenvs/scipy_meson/share/man/man1/meson.1
    /home/br/.virtualenvs/scipy_meson/share/polkit-1/actions/com.mesonbuild.install.policy
Proceed (Y/n)? y
  Successfully uninstalled meson-0.59.2
(scipy_meson) br@gonzales:~/sweethome/temp/meson_scipy/scipy$ pip install pip install git+https://github.com/mesonbuild/meson.git@master
Collecting git+https://github.com/mesonbuild/meson.git@master

the build succeeds. Running the tests now. The remaining annoyance is

Program cython found: YES (/home/br/.virtualenvs/scipy_meson/bin/cython)
Program pythran found: YES (/home/br/.virtualenvs/scipy_meson/bin/pythran)
Program python3 found: YES (/home/br/.virtualenvs/scipy_meson/bin/python)
WARNING: Broken python installation detected. Python files installed by Meson might not be found by python interpreter.
 This warning can be avoided by setting "python.platlibdir" option.
WARNING: Broken python installation detected. Python files installed by Meson might not be found by python interpreter.
 This warning can be avoided by setting "python.purelibdir" option.

during the setup stage, and finally install is into python3/dist-packages (same as ev-br/mc_lib#45)

Installing /home/br/sweethome/temp/meson_scipy/scipy/scipy/io/harwell_boeing/tests/__init__.py to /home/br/sweethome/temp/meson_scipy/scipy/installdir/lib/python3/dist-packages/scipy/io/harwell_boeing/tests
Installing /home/br/sweethome/temp/meson_scipy/scipy/scipy/io/harwell_boeing/tests/test_fortran_format.py to /home/br/sweethome/temp/meson_scipy/scipy/installdir/lib/python3/dist-packages/scipy/io/harwell_boeing/tests
Installing /home/br/sweethome/temp/meson_scipy/scipy/scipy/io/harwell_boeing/tests/test_hb.py to /home/br/sweethome/temp/meson_scipy/scipy/installdir/lib/python3/dist-packages/scipy/io/harwell_boeing/tests

@ev-br
Copy link
Author

ev-br commented Oct 10, 2021

One more issue, with stock BLAS/ATLAS. Many copies of

$ python -c'import scipy; scipy.test()'
========================================================== test session starts ==========================================================
platform linux -- Python 3.8.10, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: /home/br/sweethome/temp/meson_scipy/scipy, configfile: pytest.ini
collected 928 items / 224 errors / 18 deselected / 686 selected                                                                         

================================================================ ERRORS =================================================================
____________________ ERROR collecting installdir/lib/python3/dist-packages/scipy/cluster/tests/test_disjoint_set.py _____________________
ImportError while importing test module '/home/br/sweethome/temp/meson_scipy/scipy/installdir/lib/python3/dist-packages/scipy/cluster/tests/test_disjoint_set.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.8/importlib/__init__.py:127: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
scipy/installdir/lib/python3/dist-packages/scipy/cluster/__init__.py:25: in <module>
    from . import vq, hierarchy
scipy/installdir/lib/python3/dist-packages/scipy/cluster/vq.py:72: in <module>
    from scipy.spatial.distance import cdist
scipy/installdir/lib/python3/dist-packages/scipy/spatial/__init__.py:101: in <module>
    from ._procrustes import procrustes
scipy/installdir/lib/python3/dist-packages/scipy/spatial/_procrustes.py:9: in <module>
    from scipy.linalg import orthogonal_procrustes
scipy/installdir/lib/python3/dist-packages/scipy/linalg/__init__.py:195: in <module>
    from .misc import *
scipy/installdir/lib/python3/dist-packages/scipy/linalg/misc.py:3: in <module>
    from .blas import get_blas_funcs
scipy/installdir/lib/python3/dist-packages/scipy/linalg/blas.py:213: in <module>
    from scipy.linalg import _fblas
E   ImportError: /home/br/sweethome/temp/meson_scipy/scipy/installdir/lib/python3/dist-packages/scipy/linalg/_fblas.cpython-38-x86_64-linux-gnu.so: undefined symbol: cspmv_

But that goes under a different rubric, as in "improve blas/lapack detection" for openblas alternatives.

@rgommers
Copy link
Owner

Thanks! I haven't seen WARNING: Broken python installation detected., so will look into that.

@ev-br
Copy link
Author

ev-br commented Oct 12, 2021

mesonbuild/meson#9388 (comment) indicates that the warning is probably going to stay as it's related to a heuristics meson applies to work around Debian/Ubuntu interaction with virtualenvs (and likely other virtual environments on debian derivatives).

@ev-br
Copy link
Author

ev-br commented Oct 12, 2021

Ok, so the original problem was a user fluke, which is now fixed by the meson master, so this one can be closed. Or do you want me to keep this issue open for the openblas alternatives?

@rgommers
Copy link
Owner

Not for OpenBLAS, but let's leave it open for the "broken Python" warning - I'm seeing it on Arch Linux as well, so it's almost certainly incorrectly triggered.

@eli-schwartz
Copy link

In fact the warning is only printed when meson evaluates the build setup and concludes that it believes meson install -C builddir will install to a location that is not on your (virtualenv python) sys.path.

@rgommers
Copy link
Owner

That warning will be unexpected then. I expected development builds to do this standard, and also wheel builds - install to a custom prefix, then use PYTHONPATH or install a .pth file to point to that prefix.

Note that python setup.py build_ext -i will also not emit such a warning, nor do I think any other build tool does. It just seems conceptually wrong - there must be a separation between build and install steps, Meson is the only build tool in use, but there can be many ways to install the result of a build.

@eli-schwartz
Copy link

eli-schwartz commented Oct 14, 2021

setup.py has no concept of a pre-compilation step which runs before build_ext but computes the paths which will be used by install. It actually has nothing to do with separating build vs. install, but rather about separating configure vs. install with build standing off to the side.

As for the install step, setup.py is blessed to run in a python only world, does not compute the standard GNU install directories, and cannot handle mixed-language code (it unofficially supports "data files" as long as they are installed to sys.prefix but the authors consider this deprecated, and cannot install outside that at all). In return, it's very good at installing to the correct location always. I suppose it wasn't considered important to implement a message during setup.py install that is never reached. :)

Pip on the other hand, will in fact warn you if it installs an entry point to a location that isn't on PATH. This seems reasonable.

...

In-place builds aren't supported at all, so that's a bad comparison to make. The structured sources proposal in meson might solve this and make meson devenv a reliable way to set the PYTHON PATH to point at a working editable install with mixed .py and extension modules (this could also be used via .pth files of course, at the pep 517 backend level). I have alternative ideas along these lines as well.

None of this makes the idea of ensuring that meson install installs to somewhere that actually works out of the box, less important. I don't consider "just set your PYTHONPATH" to be a viable long term solution, and emitting a warning that it won't work out of the box seems not unreasonable. If you're going to make it work anyway using non-default manual steps then of course you may ignore the warning...

(I am pretty sure you don't actually want to do it that way, and you're just working around the fact that editable installs aren't implemented.)

@rgommers
Copy link
Owner

Pip on the other hand, will in fact warn you if it installs an entry point to a location that isn't on PATH. This seems reasonable.

It may be, but pip does that at the "install for a user" stage - not the same as meson install. Doing it in the configure stage is also the wrong place (principle: never emit warnings for correct usage). It's not just use of PYTHONPATH (or devenv) for development purposes, you can also just be building a wheel, or a conda package.

None of this makes the idea of ensuring that meson install installs to somewhere that actually works out of the box, less important.

No, I disagree. meson install installs the build output, it's the very first place where you assemble Python source and compiled extensions in a single place. It's what you then need to post-process into any kind of packaging artifact (wheel, conda package, RPM, etc.). There's no way to avoid using meson install here I think, even though you never want/need import mypackage to work.

To stay with Pip: pip will invoke the actual build system (Meson), and may ask it to do all its work in /tmp for example. It then gets back a wheel, which is the thing that gets unpacked into a path from where it must be importable. Why do you want to raise a warning for this? It's just all valid, idiomatic use unless I'm missing something.

(I am pretty sure you don't actually want to do it that way, and you're just working around the fact that editable installs aren't implemented.)

Actually, we're mostly avoiding editable installs, because it makes the dev use an extra layer (like pip) which does unwanted things like hide the build log. So yeah, I'd rather not use PYTHONPATH but something like conda develop to install a .pth file - but either way I don't want to see a confusing warning.

Possible solution

If you want to keep it enabled by default, can we have a simple way to turn it off? I don't have a project where I'm producing both Python packages and non-Python package, nor do I need to care about GNU install directories. So I'd just like something like check_python_import_path: false.

The python.purelibdir and python.platlibdir things don't seem usable to me to disable this warning. Reading https://mesonbuild.com/Builtin-options.html#module-options, it wants absolute paths, which is impossible to know as a developer of a project.

@rgommers
Copy link
Owner

rgommers commented Nov 3, 2021

@FFY00 pointed out that I likely should be using meson install --destdir rather than meson install --prefix in order to install to a local directory for, say, a dev build. Trying that:

# On Arch Linux, using a Python from a conda env:
$ meson setup build
$ ninja -C build  # warns about platlibdir etc.

# To test (this is wrong):
$ meson install -C build
<asks for permissions to run as super user because the default location is /usr - deny those>

# Now try --destdir:
$ meson install -C build --destdir installdir
... <many lines of output, last one is:>
Installing /home/rgommers/code/bldscipy/scipy/io/harwell_boeing/tests/test_hb.py to /home/rgommers/code/bldscipy/build/installdir/usr/local/lib/python3.9/site-packages/scipy/io/harwell_boeing/tests

Conclusion of the above: yes I should be using --destdir for installing outside of a prefix, and no it's not a replacement for --prefix (paths picked up in install are still for the Python in /usr/local/, which isn't involved in anything).

So it seems like I should do both here:

  1. use --prefix to point to the dir above the one for the python I want to be using
  2. use --destdir if I'm not installing to site-packages of that python, but to for example an in-tree dir

Does this work? It seems not:

$ rm -rf build
$ which python
/home/rgommers/anaconda3/envs/scipy-meson/bin/python
$ meson setup build --prefix /home/rgommers/anaconda3/envs/scipy-meson
...
Program python3 found: YES (/home/rgommers/anaconda3/envs/scipy-meson/bin/python3.9)
WARNING: Broken python installation detected. Python files installed by Meson might not be found by python interpreter.
 This warning can be avoided by setting "python.platlibdir" option.
WARNING: Broken python installation detected. Python files installed by Meson might not be found by python interpreter.
 This warning can be avoided by setting "python.purelibdir" option.
...
  User defined options
    prefix: /home/rgommers/anaconda3/envs/scipy-meson
...

Why is this still showing the warnings? If there is one targets out of the many I have that points to a path outside of the prefix, how do I find it? meson introspect --installed (or --install-plan) output is super long, and from a manual inspection I don't see anything wrong (also, all tests pass so I'm fairly sure install paths are correct and the warning is spurious).

@rgommers rgommers changed the title meson / virtualenv / ubuntu : fails to build scipy Issues with prefix/destdir and "Broken python installation detected" warnings Nov 3, 2021
@tirthasheshpatel
Copy link

When I try to build in a virtual environment created using venv or virtualenv, it fails to form an absolute path to the numpy include directories:

(scipy-meson) tirthasheshpatel@tirthap:~/Desktop/scipy_meson$ meson setup build --prefix=$PWD/install
...
scipy/meson.build:34:0: ERROR: Tried to form an absolute path to a source dir.
You should not do that but use relative paths instead.

To get include path to any directory relative to the current dir do

incdir = include_directories(dirname)

After this incdir will contain both the current source dir as well as the
corresponding build dir. It can then be used in any subdirectory and
Meson will take care of all the busywork to make paths work.

Dirname can even be '.' to mark the current directory. Though you should
remember that the current source and build directories are always
put in the include directories by default so you only need to do
include_directories('.') if you intend to use the result in a
different subdirectory.

From build/meson-logs/meson-log.txt:

Running command: /home/tirthasheshpatel/Desktop/scipy_meson/scipy-meson/bin/python -c import os; os.chdir(".."); import numpy; print(numpy.get_include())
--- stdout ---
/home/tirthasheshpatel/Desktop/scipy_meson/scipy-meson/lib/python3.9/site-packages/numpy/core/include

--- stderr ---



scipy/meson.build:34:0: ERROR: Tried to form an absolute path to a source dir.
You should not do that but use relative paths instead.

To get include path to any directory relative to the current dir do

incdir = include_directories(dirname)

After this incdir will contain both the current source dir as well as the
corresponding build dir. It can then be used in any subdirectory and
Meson will take care of all the busywork to make paths work.

Dirname can even be '.' to mark the current directory. Though you should
remember that the current source and build directories are always
put in the include directories by default so you only need to do
include_directories('.') if you intend to use the result in a
different subdirectory.

To verify that this is the case, I replaced the inc_np at line 34 in scipy/meson.build with the path in my virtual env:

diff --git a/scipy/meson.build b/scipy/meson.build
index 3f6698a73..cdd394a4a 100644
--- a/scipy/meson.build
+++ b/scipy/meson.build
@@ -31,7 +31,7 @@ incdir_numpy = run_command(py3,
   check: true
 ).stdout().strip()
 
-inc_np = include_directories(incdir_numpy)
+inc_np = include_directories('/home/tirthasheshpatel/Desktop/scipy_meson/scipy-meson/lib/python3.9/site-packages/numpy/core/include')
 
 incdir_f2py = incdir_numpy / '..' / '..' / 'f2py' / 'src'
 inc_f2py = include_directories(incdir_f2py)

and built using a local meson installation outside of the virtual env in my system and it fails with the same error. Is there any way I could use meson in a virtual environment built using venv or virtualenv?

Steps to reproduce:

# I use Python3.9
python3.9 -m virtualenv scipy-meson
source scipy-meson/bin/activate
python -m pip install -U pip
pip install numpy cython pythran pybind11 meson==0.60.1 ninja
meson setup build --prefix=$PWD/install

@rgommers
Copy link
Owner

@tirthasheshpatel is this happening with both meson 0.60.0 and master?

@tirthasheshpatel
Copy link

tirthasheshpatel commented Nov 19, 2021

@tirthasheshpatel is this happening with both meson 0.60.0 and master?

Yes (tried with 0.60.0, 0.60.1, master)

@rgommers
Copy link
Owner

Also, what distro?

@tirthasheshpatel
Copy link

tirthasheshpatel commented Nov 19, 2021

Distributor ID:	Ubuntu
Description:	Ubuntu 20.04.3 LTS
Release:	20.04
Codename:	focal

@rgommers
Copy link
Owner

scipy/meson.build:34:0: ERROR: Tried to form an absolute path to a source dir.
You should not do that but use relative paths instead.

I haven't been able to reproduce this yet, but it's the second time I've seen it. Maybe be related to scipy#14890, IIRC that's why we needed an absolute path - file writing seemed to need it, can't remember the details but likely because had to do with it having to do the right thing for both distutils and meson based builds, and those are writing files to different directories (in-place, or to the build dir).

@tirthasheshpatel
Copy link

tirthasheshpatel commented Nov 19, 2021

Hmm, not sure if it is related to Cython code generation. If I am not wrong, meson fails during the setup stage before generating any files... We call include_directories(incdir_numpy) which is supposed to return a relative path given an absolute path, according to my understanding, but it fails. So, I thought I was using meson incorrectly.

@rgommers
Copy link
Owner

Ah I remember you mentioned this a week ago, and it's only broken in your Ubuntu virtualenv, outside of virtualenv it's fine: scipy#14847 (comment). I added this to the tracking issue. Debian/Ubuntu is known to make a giant mess out of virtualenvs (and Python sysconfig et al.), so I think I'd like to put this lower on the TODO list. We should add a CI job for this situation. It's also not the same issue as the prefix/destdir one that this issue was originally about.

For now I'd say, if you're on Ubuntu, avoid a virtualenv, or use conda. It may be a "bug" in Meson, but only because Debian is completely messed up - see mesonbuild/meson#8739.

@tirthasheshpatel
Copy link

Thanks for your help! I will use conda in the meantime.

@ev-br
Copy link
Author

ev-br commented Nov 19, 2021

For now I'd say, if you're on Ubuntu, avoid a virtualenv,

Ugh, that's a bit of an advice :-). On my previous attempts, it did work despite an unhelpful warning . That was on meson master, pre-0.60.

Virtualenv on ubuntu is a perfectly valid and mainstream use case.
TBH, all this finger-pointing into debian is not very helpful.

@rgommers
Copy link
Owner

Virtualenv on unbuntu is a perfectly valid and mainstream use case.

We'll fix it well before switching over to Meson as the default, no worries. I just want to finally merge support into SciPy master first, and ensure wheel build and Windows work - that's more important than this virtualenv-on-debian specific issue. If it was easy we'd just do it now, but it is not.

@tirthasheshpatel
Copy link

tirthasheshpatel commented Nov 19, 2021

On my previous attempts, it did work despite an unhelpful warning .

@ev-br Did you install meson in your virtual env? I think meson could pick up on numpy C sources outside virtual envs if a local installation is used. Can you share your meson logs (builddir/meson-logs/meson-log.txt) which should have the numpy C sources used?

@ev-br
Copy link
Author

ev-br commented Nov 19, 2021

@tirthasheshpatel I just realized why I'm notified in this issue :-). My attempts are reported above, and I don't think I've kept the logs beyond what's up there.

And I definitely installed everything into the virtualenv --- I don't think I even have numpy installed outside of a virtualenv.

@eli-schwartz
Copy link

It seems that your virtualenv is a subdirectory of the scipy repository?

@rgommers
Copy link
Owner

It seems that your virtualenv is a subdirectory of the scipy repository?

No, that's the same "issue" as we've been discussion higher up (see #82 (comment)).

It should be irrelevant here. @tirthasheshpatel can confirm that just a plain meson setup build without using --prefix at all will still fail with scipy/meson.build:34:0: ERROR: Tried to form an absolute path to a source dir. I believe.

@rgommers
Copy link
Owner

I do hope your work-in-progress install_env=auto will help here though @eli-schwartz

@eli-schwartz
Copy link

My point is that this seems to be entirely unrelated to prefix.

Prefix and how to handle it, has an effect on whether meson warns you that files will be installed outside of the PYTHONPATH. It's not actually a meson error, it's just bad defaults for installing.

Virtualenvs being inside the source tree have an effect on whether string literals passed from subprocesses (that run numpy code and print header paths) to meson's include_directories, are absolute paths which meson objects for purposes of codegen, and actually raises a configure-time error.

Imagine that numpy isn't involved, and some developer somewhere makes a project in /home/me/Projects/foobar/, and embeds, in the build files which are checked into git, the actual path /home/me/Projects/foobar/headers/.

Meson lints this sort of thing, and it doesn't have any way of knowing that /home/me/Projects/foobar/venv/lib/python3.9/site-packages/numpy/core/include/ is "different, because that isn't checked into git, it's just a project dependency that happens to downloaded and installed there".

One way to let meson know that this is a dependency is to go through the subproject system, build numpy with meson, and expose a meson.override_dependency() which builds a relative include path and exports it for use by the superproject.

The other solution is just "don't do that", build your virtualenv one directory upward so it isn't a child node of the scipy source tree.

If you have any ideas for a potential third solution I'm all ears. :) But I'm not sure how to allow it for numpy without allowing it for include_directories('/home/me/Projects/foobar/headers/')

@rgommers
Copy link
Owner

Virtualenvs being inside the source tree

It's not in the source tree, the virtualenv is elsewhere. It's just that the in-tree install location is what is recommended by my install script. So you can do development work, and git clean -xdf to get rid of it.

My point is that this seems to be entirely unrelated to prefix.

Yes I agree. I just don't understand why it breaks in this Ubuntu virtualenv, and it works without virtualenvs.

One way to let meson know that this is a dependency is to go through the subproject system, build numpy with meson, and expose a meson.override_dependency() which builds a relative include path and exports it for use by the superproject.

We definitely cannot require building numpy in order to build scipy. That should also not be needed. If the problem is that this is not allowed:

# NumPy include directory - needed in all submodules
incdir_numpy = run_command(py3,
  [
    '-c',
    'import os; os.chdir(".."); import numpy; print(numpy.get_include())'
  ],
  check: true
).stdout().strip()

inc_np = include_directories(incdir_numpy)

Then we just need to build NumPy support into Meson, so dependency('numpy') simply works. Which is a good idea anyway, and was on my TODO list - because the stdout scraping isn't pretty. Also this is what CMake has done too.

@rgommers
Copy link
Owner

(and no, numpy doesn't have pkg-config support, and we need to support already shipped numpy versions, so just relying on pkg-config to make dependency('numpy') work is not possible).

@rgommers
Copy link
Owner

It's not in the source tree, the virtualenv is elsewhere

Oh wait, it was?? Then I agree with "don't do that".

@tirthasheshpatel
Copy link

Oh wait, it was??

Yes, it was. But I created a fresh venv in a different directory but still got the same error.

Meson Log
Build started at 2021-11-19T22:50:37.897126
Main binary: /home/tirthasheshpatel/Desktop/scipy_meson_venv/scipy-meson/bin/python
Build Options: -Dprefix=/home/tirthasheshpatel/Desktop/scipy_meson/install
Python system: Linux
The Meson build system
Version: 0.60.1
Source dir: /home/tirthasheshpatel/Desktop/scipy_meson
Build dir: /home/tirthasheshpatel/Desktop/scipy_meson/build
Build type: native build
Project name: SciPy
Project version: 1.7.0.dev0+ababababab
Sanity testing C compiler: ccache cc
Is cross compiler: False.
Sanity check compiler command line: ccache cc sanitycheckc.c -o sanitycheckc.exe -Wno-unused-function -Wno-conversion -Wno-unused-but-set-variable -Wno-misleading-indentation -Wno-incompatible-pointer-types -D_FILE_OFFSET_BITS=64
Sanity check compile stdout:

-----
Sanity check compile stderr:

-----
Running test binary command: /home/tirthasheshpatel/Desktop/scipy_meson/build/meson-private/sanitycheckc.exe
C compiler for the host machine: ccache cc (gcc 9.3.0 "cc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0")
C linker for the host machine: cc ld.bfd 2.34
Sanity testing C++ compiler: ccache c++
Is cross compiler: False.
Sanity check compiler command line: ccache c++ sanitycheckcpp.cc -o sanitycheckcpp.exe -D_FILE_OFFSET_BITS=64
Sanity check compile stdout:

-----
Sanity check compile stderr:

-----
Running test binary command: /home/tirthasheshpatel/Desktop/scipy_meson/build/meson-private/sanitycheckcpp.exe
C++ compiler for the host machine: ccache c++ (gcc 9.3.0 "c++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0")
C++ linker for the host machine: c++ ld.bfd 2.34
Running compile:
Working directory:  /tmp/tmpv5re1hgp
Command line:  cython /tmp/tmpv5re1hgp/testfile.pyx -o /tmp/tmpv5re1hgp/output.exe --fast-fail 

Code:
 print("hello world")
Compiler stdout:
 
Compiler stderr:
 /home/tirthasheshpatel/Desktop/scipy_meson_venv/scipy-meson/lib/python3.9/site-packages/Cython/Compiler/Main.py:369: FutureWarning: Cython directive 'language_level' not set, using 2 for now (Py2). This will change in a later release! File: /tmp/tmpv5re1hgp/testfile.pyx
  tree = Parsing.p_module(s, pxd, full_module_name)

Cython compiler for the host machine: cython (cython 0.29.24)
Sanity testing C compiler: ccache cc
Is cross compiler: False.
Sanity check compiler command line: ccache cc sanitycheckc.c -o sanitycheckc.exe -D_FILE_OFFSET_BITS=64
Sanity check compile stdout:

-----
Sanity check compile stderr:

-----
Running test binary command: /home/tirthasheshpatel/Desktop/scipy_meson/build/meson-private/sanitycheckc.exe
C compiler for the build machine: ccache cc (gcc 9.3.0 "cc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0")
C linker for the build machine: cc ld.bfd 2.34
Sanity testing C++ compiler: ccache c++
Is cross compiler: False.
Sanity check compiler command line: ccache c++ sanitycheckcpp.cc -o sanitycheckcpp.exe -D_FILE_OFFSET_BITS=64
Sanity check compile stdout:

-----
Sanity check compile stderr:

-----
Running test binary command: /home/tirthasheshpatel/Desktop/scipy_meson/build/meson-private/sanitycheckcpp.exe
C++ compiler for the build machine: ccache c++ (gcc 9.3.0 "c++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0")
C++ linker for the build machine: c++ ld.bfd 2.34
Using cached compile:
Cached command line:   

Code:
 print("hello world")
Cached compiler stdout:
 
Cached compiler stderr:
 /home/tirthasheshpatel/Desktop/scipy_meson_venv/scipy-meson/lib/python3.9/site-packages/Cython/Compiler/Main.py:369: FutureWarning: Cython directive 'language_level' not set, using 2 for now (Py2). This will change in a later release! File: /tmp/tmpv5re1hgp/testfile.pyx
  tree = Parsing.p_module(s, pxd, full_module_name)

Cython compiler for the build machine: cython (cython 0.29.24)
Build machine cpu family: x86_64
Build machine cpu: x86_64
Host machine cpu family: x86_64
Host machine cpu: x86_64
Target machine cpu family: x86_64
Target machine cpu: x86_64
Fortran compiler for the host machine: gfortran (gcc 9.3.0 "GNU Fortran (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0")
Fortran linker for the host machine: gfortran ld.bfd 2.34
Program cython found: YES (/home/tirthasheshpatel/Desktop/scipy_meson_venv/scipy-meson/bin/cython)
Program pythran found: YES (/home/tirthasheshpatel/Desktop/scipy_meson_venv/scipy-meson/bin/pythran)
Program cp found: YES (/usr/bin/cp)
Program python3 found: YES (/home/tirthasheshpatel/Desktop/scipy_meson_venv/scipy-meson/bin/python)
WARNING: Broken python installation detected. Python files installed by Meson might not be found by python interpreter.
 This warning can be avoided by setting "python.platlibdir" option.
WARNING: Broken python installation detected. Python files installed by Meson might not be found by python interpreter.
 This warning can be avoided by setting "python.purelibdir" option.
Pkg-config binary for MachineChoice.HOST is not cached.
Pkg-config binary missing from cross or native file, or env var undefined.
Trying a default Pkg-config fallback at pkg-config
Found pkg-config: /usr/bin/pkg-config (0.29.1)
Determining dependency 'python-3.9' with pkg-config executable '/usr/bin/pkg-config'
env[PKG_CONFIG_LIBDIR]: /usr/lib/x86_64-linux-gnu/pkgconfig
env[PKG_CONFIG_PATH]: 
Called `/usr/bin/pkg-config --modversion python-3.9` -> 0
3.9
env[PKG_CONFIG_LIBDIR]: /usr/lib/x86_64-linux-gnu/pkgconfig
env[PKG_CONFIG_PATH]: 
Called `/usr/bin/pkg-config --cflags python-3.9` -> 0
-I/usr/include/python3.9 -I/usr/include/x86_64-linux-gnu/python3.9
env[PKG_CONFIG_LIBDIR]: /usr/lib/x86_64-linux-gnu/pkgconfig
env[PKG_CONFIG_ALLOW_SYSTEM_LIBS]: 1
env[PKG_CONFIG_PATH]: 
Called `/usr/bin/pkg-config --libs python-3.9` -> 0

env[PKG_CONFIG_LIBDIR]: /usr/lib/x86_64-linux-gnu/pkgconfig
env[PKG_CONFIG_PATH]: 
Called `/usr/bin/pkg-config --libs python-3.9` -> 0

Running command: /home/tirthasheshpatel/Desktop/scipy_meson_venv/scipy-meson/bin/python -c import os; os.chdir(".."); import numpy; print(numpy.get_include())
--- stdout ---
/home/tirthasheshpatel/Desktop/scipy_meson_venv/scipy-meson/lib/python3.9/site-packages/numpy/core/include

--- stderr ---



scipy/meson.build:34:0: ERROR: Tried to form an absolute path to a source dir.
You should not do that but use relative paths instead.

To get include path to any directory relative to the current dir do

incdir = include_directories(dirname)

After this incdir will contain both the current source dir as well as the
corresponding build dir. It can then be used in any subdirectory and
Meson will take care of all the busywork to make paths work.

Dirname can even be '.' to mark the current directory. Though you should
remember that the current source and build directories are always
put in the include directories by default so you only need to do
include_directories('.') if you intend to use the result in a
different subdirectory.


@eli-schwartz
Copy link

That actually appears to be a legit bug.

Given /path/to/source/ as a meson project, you cannot use /path/to/source-extrastuff/ without meson erroneously thinking that -extrastuff is a subdirectory of the source. This is just bad path parsing on meson's side.

@rgommers I'd be happy to mentor and/or review+merge a numpy dependency for https://mesonbuild.com/Dependencies.html#dependencies-with-custom-lookup-functionality

(I may or may not spontaneously find time to implement that myself.)

@rgommers
Copy link
Owner

@rgommers I'd be happy to mentor and/or review+merge a numpy dependency for https://mesonbuild.com/Dependencies.html#dependencies-with-custom-lookup-functionality

Thanks! Let me open a Meson issue so we keep track of it and do it all at once (e.g. we need numpy.f2py and numpy.random include dirs as well).

@zhangyiwei
Copy link

I've seen exactly the same before and was able to fix it by uninstalling meson and reinstalling via pip. e.g. "python3 -m pip install meson" and then set the PATH to include "~/.local/bin". Now this pip installed "meson" understands python locations, and the warning is gone. Hopefully that applies to your case as well.

@rgommers
Copy link
Owner

To record the current state:

@ev-br
Copy link
Author

ev-br commented Jan 30, 2022

Yup, can confirm that the virtualenv on ubuntu focal (the OP issue) works fine with meson 0.61.1. I only tested 0.61.1 and only with virtualenv (no stdlib venv, no user installs outside of a virtualenv). Which is superb, and goes 99% of the way, I'd say. The warning is mostly harmless IMO (will need to be documented to be ignored, and duly ignored, I'd think).

@rgommers
Copy link
Owner

Thanks, let me close this then.

@tirthasheshpatel
Copy link

tirthasheshpatel commented Jan 31, 2022

Also tested on my ubuntu focal with meson 0.61.1 and virtualenv and everything works seamlessly. I love the speed: from 30-40 minutes of build time using distutils to 2-3 minutes (on 8 cores) using meson & ninja!! It would be a cheery on the cake to get mesonbuild/meson#9788 in 0.62.0! Thanks @rgommers and Meson team for working on this!

@eli-schwartz
Copy link

The python.install_env option is now merged to meson git master and will be present in 0.62.0.

@rgommers
Copy link
Owner

Awesome! Thanks again @eli-schwartz. When 0.62.0 is out I will make it the minimum required version and add -Dpython.install_env=auto in the appropriate places in docs and scripts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants