Although the currently accepted answer proposes the right approach to being able to deactivate a virtual environment, the reason why it doesn't work as you may have though is not technically right.
As described in the documentation:
When it is time to execute recipes to update a target, they are executed by invoking a new sub-shell for each line of the recipe [...]
Please note: this implies that setting shell variables and invoking shell commands such as cd that set a context local to each process will not affect the following lines in the recipe[...]
So the reason that you can't deactivate a virtual environment on its own recipe line is that the deactivate
function that is stored in the caller shell memory does not exist in the shell Make creates for that line.
Assuming that I have these versions of Python installed on my workstation:
temp% py -0
-V:3.11 * Python 3.11 (64-bit)
-V:3.8 Python 3.8 (64-bit)
-V:3.7 Python 3.7 (64-bit)
-V:2.7 Python 2.7
We assume that my default Python version is 3.11, and we'll create a virtual environment using version 3.8, just so that when we do python -V, we printout the currently used version. With the Makefile:
pymakevenv:
@py -3.8 -m venv myvenv
pyvenvtestgood:
@source myvenv/Scripts/activate;python -V;deactivate;python -V
pyvenvtestbad:
@source myvenv/Scripts/activate;python -V
@python -V;deactivate;python -V
We can get the following results:
temp% gmake pymakevenv
temp% gmake pyvenvtestgood
Python 3.8.10
Python 3.11.3
temp% gmake pyvenvtestbad
Python 3.8.10
Python 3.11.3
/usr/bin/sh: deactivate: command not found
Python 3.11.3
temp%
In pyvenvtestbad
, we see that the deactivate
function set on the first line is no longer there on the second line.