If Python is not found, the python bindings are not activated. If, however, during the setup of the python bindings some python requirement cannot be fulfilled (and also not automatically installed), CMake raises a hard error. This happened, e.g., in a Linux Mint 19 system (based on Ubuntu 18.04) with an unusable pip. Warning are shown and the hard error message indicates how to solve the problem, but for those who do not want to use any python bindings this is annoying, because it is absolutely not needed for the c++ library.
Proposed solution: transform FATA_ERRORs in CMake into WARNING and deactivate the python bindings instead. Maybe collect all these problems in a variable DUNE_PYTHON_BINDINGS_REQUIREMENTS_FOUND that is set to FALSE in any of the current FATAL_ERROR cases.
The issue is not a hard error during the installation of the requirements for the python bindings. A problem there leads to a warning only. The issue is a hard error when setting up the internal venv and pip is not available.
@simon.praetorius: IMHO: There should not be any FATAL_ERROR when checking for the requirements of the Python binding. Instead, if any requirement is not fulfilled, the bindings should be disabled. So, a slightly softer approach would be more appropriate. This could, probably, easily be done by changing some FATAL_ERROR to WARNING + setting the option DUNE_ENABLE_PYTHONBINDINGS=FALSE.
IMHO: There should not be any FATAL_ERROR when checking for the requirements of the Python binding. Instead, if any requirement is not fulfilled, the bindings should be disabled. So, a slightly softer approach would be more appropriate. This could, probably, easily be done by changing some FATAL_ERROR to WARNING + setting the option DUNE_ENABLE_PYTHONBINDINGS=FALSE.
In that case it would be good if a clear message is printed somewhere, ideally in the summary that python bindings were disable, because requirement xy was not fulfilled.
In DunePythonInstallPackages was have at the moment
dune_execute_process(COMMAND ${DUNE_PYTHON_VIRTUALENV_EXECUTABLE} -m pip install ... RESULT_VARIABLE DUNE_PYTHON_DEPENDENCIES_FAILED WARNING_MESSAGE "python package requirements could not be installed - possibly connection to the python package index failed")if(DUNE_PYTHON_DEPENDENCIES_FAILED)set(DUNE_PYTHON_VENVSETUP FALSE CACHE BOOL "The internal venv setup failed: some required packages could not be installed")return()endif()
So it fails with a warning (not in the summary) that the required packages could not be installed. Here we already assume pip was found. Before that we have in the same file
if(NOT DUNE_PYTHON_pip_FOUND)message(WARNING "dune_python_install_package: Requested installations, but pip was not found!")set(DUNE_PYTHON_VENVSETUP FALSE CACHE BOOL "The internal venv setup failed due to missing pip")return()endif()
So this already allows the configuration to continue.
The failure happens in DunePythonVirtualEnv.cmake as @simon.praetorius wrote. We could easily make that error into a warning as well. I tried that (removing my pip locally) and that then completes the configuration with two warnings but of course at this point no information in the summary. We could remove the warning in DunePythonInstallPackages since that is redundant.
PS: The cache variable DUNE_PYTHON_VENVSETUP is not correctly named since the internal venv setup has worked it's only the Python bindings that will not be correctly added due to missing requirements. It's used to disable running the dune_python_add_test command (DunePythonTestCommand) and should probably be renamed.
In DunePythonVirtualEnv.cmake there are some places that could be improved in this regard, e.g.,
# DunePythonVirtualEnv.cmake:132if(NOT(DUNE_PYTHON_virtualenv_FOUND OR DUNE_PYTHON_venv_FOUND))message(FATAL_ERROR "One of the python packages virtualenv/venv is needed on the host system!")endif()
could be changed to
# DunePythonVirtualEnv.cmake:132if(NOT(DUNE_PYTHON_virtualenv_FOUND OR DUNE_PYTHON_venv_FOUND))message(WARNING "One of the python packages virtualenv/venv is needed on the host system!")set(DUNE_ENABLE_PYTHONBINDINGS FALSE)return()endif()
For completeness, another solution would be to invest time in solving #279 (closed). If solved, this would obliviate the "if requ x not found disable Python" logic.
So one would always need to run install before testing anything in a module. This would also influence the way dune-testtools can be used - I wasn't aware that you wanted to change that as well.
I consider dune-testtools a completely different case because there a pure Python package has to be installed to be used during configure time by CMake. That's quite a special case. I would be fine with documenting in dune-testtools that you need to manually do so, before configuring Dune. But maybe there is other used cases with Python modules where none of the approaches would work... Getting off-track for this issue here...
@simon.praetorius@andreas.dedner FYI, I can reproduce the initial error in a fresh ubuntu (20.04 in my case) that doesn't have python3-venv installed via aptitude. Then I get this warning + error (the error doesn't match the actual problem but the warning suggests the solution)
-- WARNING: Failed to build a virtual env with pip installed, trying again without pip#18 4.679 -- If you are using Debian or Ubuntu, consider installing python3-venv and / or python-virtualenv#18 4.768 CMake Error at cmake/modules/DunePythonVirtualenv.cmake:241 (message):#18 4.768 dune-common set up a virtualenv, but needs pip to be installed into it.
In any case, this should not be a fatal error as suggested in this issue.
docker build -t minimal --build-arg DUNE_BRANCH=master . to reproduce the error
Dockerfilegcc.minimal.opts
I missed that - that would be before the place where the current fatal error is coming up in line 241 which is where I changed the error to warning (a return wasn't required there). I'm not sure I understand the logic here - first one tries to setup a venv without pip (line 176) but then fails because pip is not available? In line 222 there is the check for DUNE_PYTHON_ALLOW_GET_PIP but that was also done previously in line 156.
Is there a reason to not at least replace that fatal error with a warning during the setup of the virtual env now?
As I said above the problem is gone then - one gets two warning and no nice message in the summary but that is then a different issue. We seem to all agree that there should be no hard error when setting up the internal venv. That is just still there from Dominic's original version where the internal venv had to be activated separately and then a hard error made sense.
Does this work? A warning does not stop the execution and in the next step you call functions relying on the found venv or found pip. Or do you mean, warning + return? If it is tried out and works, I'm perfectly fine with a simple solution :-)
I mean warning + return which I tested and it least it worked for the one setting I tested. I don't know how to check this for example in the nightly build. Perhaps if we had a image without python-dev then we could have one of the pipelines use that to test it?
You already get an error if you have python-dev but not python-venv, see #283 (comment 87022). This is a different case than not having python at all no?
I'm not sure whether we can write a test the starts with nothing and then step by step installs more host system packages (for python or via apt). There is, I guess, a problem with the permissions.
Of course, we could write a sequence of docker images that contain more and more packages. If proper layered images are used, this would not be too expensive.
We can possibly use a 'docker' container on the ubuntu github runner with some existing minimal image? As long as the image is setup to give sudo privileges and internet access so that apt install works within the docker image that would work?
I just tested using the docker test @tkoch provided above in the github action tests and that produced the expected error. So this seems an option for testing setup in reduced images. Would require someone to come up with a suitable bash script that starts a docker image and then successively updates the packages in such a way that in each iteration building for example dune-common to dune-grid work in each stage.
I started to build a minimal docker image for these tests: docker/ci!108 (merged) It contains only a very small set of packages, except the ubuntu default packages: ca-certificates, cmake, gcc, g++, git, make, wget. I will prepare a job in dune-common (or in the nightly tests) to run the build of dune with this setup and then step by step install more packages.
My local test revealed the following:
missing pkg-config errors in lib/dunemodules.lib (ignored)
no python3: everything compiles fine
install python3:
CMake Error at cmake/modules/DunePythonCommonMacros.cmake:97 (message): Found a Python interpreter but the Python bindings also requires the Python libraries (a package named like python-dev package or python3-devel)
install python3-dev:
-- Failed to find the python package pip with interpreter /usr/bin/python3. (missing: DUNE_PYTHON_pip_FOUND) -- Failed to find the python package virtualenv with interpreter /usr/bin/python3. (missing: DUNE_PYTHON_virtualenv_FOUND) Traceback (most recent call last): File "/duneci/modules/dune-common/cmake/scripts/pyversion.py", line 24, in <module> import pkg_resourcesModuleNotFoundError: No module named 'pkg_resources'-- Found venv_/usr/bin/python3: TRUE -- Building a virtualenv in /duneci/modules/dune-common/build-cmake/dune-env-- WARNING: Failed to build a virtual env with pip installed, trying again without pip-- If you are using Debian or Ubuntu, consider installing python3-venv and / or python-virtualenv-- Failed to find the python package pip with interpreter /duneci/modules/dune-common/build-cmake/dune-env/bin/python. (missing: pippresent) CMake Error at cmake/modules/DunePythonVirtualenv.cmake:241 (message): dune-common set up a virtualenv, but needs pip to be installed into it. You can either install it yourself manually activating the virtualenv with the activate script in your build directory /duneci/modules/dune-common/build-cmake or you set the CMake variable DUNE_PYTHON_ALLOW_GET_PIP to allow Dune to use get-pip.py from https://bootstrap.pypa.io/get-pip.py
install python3-venv:
-- Failed to find the python package pip with interpreter /usr/bin/python3. (missing: DUNE_PYTHON_pip_FOUND) -- Failed to find the python package virtualenv with interpreter /usr/bin/python3. (missing: DUNE_PYTHON_virtualenv_FOUND) Traceback (most recent call last): File "/duneci/modules/dune-common/cmake/scripts/pyversion.py", line 24, in <module> import pkg_resourcesModuleNotFoundError: No module named 'pkg_resources'
and then later in the python build:
Obtaining file:///duneci/modules/dune-common/build-cmake/python Checking if build backend supports build_editable ... error ERROR: Command errored out with exit status 1: command: /duneci/modules/dune-common/build-cmake/python/../dune-env/bin/python /duneci/modules/dune-common/build-cmake/dune-env/lib/python3.6/site-packages/pip/_vendor/pep517/in_process/_in_process.py _supported_features /tmp/tmpl5veu5x_ cwd: /duneci/modules/dune-common/build-cmake/python Complete output (10 lines): Traceback (most recent call last): File "/duneci/modules/dune-common/build-cmake/dune-env/lib/python3.6/site-packages/pip/_vendor/pep517/in_process/_in_process.py", line 363, in <module> main() File "/duneci/modules/dune-common/build-cmake/dune-env/lib/python3.6/site-packages/pip/_vendor/pep517/in_process/_in_process.py", line 345, in main json_out['return_val'] = hook(**hook_input['kwargs']) File "/duneci/modules/dune-common/build-cmake/dune-env/lib/python3.6/site-packages/pip/_vendor/pep517/in_process/_in_process.py", line 112, in _supported_features backend = _build_backend() File "/duneci/modules/dune-common/build-cmake/dune-env/lib/python3.6/site-packages/pip/_vendor/pep517/in_process/_in_process.py", line 102, in _build_backend obj = getattr(obj, path_part) AttributeError: module 'setuptools.build_meta' has no attribute '__legacy__'
Following the error message in 3., I have set the CMake variable DUNE_PYTHON_ALLOW_GET_PIP:BOOL=1. Then I get the message:
-- Installing pip using https://bootstrap.pypa.io/get-pip.py...[...]CMake Warning at cmake/modules/DunePythonInstallPackage.cmake:104 (message): dune_python_install_package: Requested installations, but pip was not found!Call Stack (most recent call first): python/CMakeLists.txt:12 (dune_python_install_package)
7. Fixing 6. by properly setting that pip is found results in the next warning/error:
CMake Warning at cmake/modules/DuneExecuteProcess.cmake:62 (message): python package requirements could not be installed - possibly connection to the python package index failed[...] Failed to build mpi4py ERROR: Could not build wheels for mpi4py, which is required to install pyproject.toml-based projects
Note, even if required packages could not be installed by pip, the targets _common and _typereqistry are still compiled. Probably this should be deactivated in case they cannot be installed and used.
The problem with mpi4py were mentioned in another issue before. A simple fix for the python-pip-error message would be to have MPI as requirement for the python bindings.
The current concept is that if HAVE_MPI is set then mpi4py is added to the requirements. The issue that the wheel can not be build is normally a warning and the package is compiled. From your description it seems that your image doesn't contain mpi? Then mpi4py should not be added (see cmake/modules/DunePythonInstallPackage.cmake:100 - do you get the message saying that mpi4py is being added?).
Not sure whether I have done this correctly. I have copied your line in the python/pyproject.toml.in file, deleted the build directory and run everything again. This results in the same error. How can I check the installed setuptools and pip versions in the virtual env?
Sorry, got that wrong place - pyproject.toml is for an isolated build which is not used for the internal venv.
Could you please try adding the setuptools>=41 to dune.module instead.
In dune.module the mpi4py package is hardcoded. Removing this, the other error above also vanishes. But then mpi4py is not available even if HAVE_MPI is true.
which branch of dune-common are you using. mpi4py in dune.module was removed in 108eda60 and shouldn't be there anymore in master. That commit also adds the code at cmake/modules/DunePythonInstallPackage.cmake:100 I mentioned above
+ if(HAVE_MPI AND NOT SKBUILD)+ message(STATUS "Adding mpi4py to the Python requirements")+ string(APPEND ProjectPythonRequires " mpi4py")+ endif()
I have created the docker image registry.dune-project.org/docker/ci/ubuntu:18.04-minimal that has a minimal set of packages only, i.e., cmake-3.13, gcc-7, g++-7, git, and no python. With this we can test that everything works fine in this setting. I have not yet found a way to incrementally install debian packages in a gitlab-ci job, although the duneci user has system rights. In a local docker run it works fine to use apt update && apt install .... Maybe someone has an idea how to transform this into a gitlab-ci job
isn't the main issue missing Internet access in the CI.
Could you wget the deb packages in the Dockerfile and install those in a script during the CI run?