I have the following python makefile.
.ONESHELL:
TEST_DIR = ./tests
DIR_NAME = $(shell date "+%Y-%m-%d_%T")
.PHONY: clean test backup env
env:
. .venv/bin/activate
test: env clean
pytest --cache-clear --cov -p no:logging --html=report.html --self-contained-html -n 8 --maxprocesses=8 $(TEST_DIR)
backup:
mkdir -p ./backup_test_results
cd ./backup_test_results
mkdir $(DIR_NAME) && cd $(DIR_NAME)
find . -name htmlcov -type d -exec cp -r '{}' ./ \;
find . \( -name "error.log" -o -name "download.log" -o -name ".coverage*" -o -name "report.html" \) -type f -exec cp '{}' ./ \;
cd ../../
clean: backup
find . -path ./.venv -prune -o \( -name __pycache__ -o -name .pytest_cache -o -name htmlcov \) -type d -exec rm -rf '{}' \;
find . \( -name "error.log" -o -name "download.log" -o -name ".coverage*" -o -name "report.html" \) -type f -delete
The directories are created as expected by using the .ONESHELL
command. But the virtual env is not getting activated.
On running the make file, there is an error which says that pytest is not found. Hence, I am assuming that virtual env was not activated.
What am I doing wrong?
.ONESHELL
doesn't mean that make starts one shell for the entire run of make and somehow passes all the commands from all the recipes to that one shell (that is not possible, because make needs to know the exit code from each recipe to know whether the rule succeeded or not).
.ONESHELL
means that all the lines in each individual recipe are passed to a single shell: by default each individual line in each individual recipe is passed to a separate shell.
So, you can't share shell environment settings between different recipes ever, even using .ONESHELL
. You could do something like this instead:
.ONESHELL:
SETVENV = . .venv/bin/activate
test: clean
$(SETVENV)
pytest --cache-clear --cov -p no:logging --html=report.html --self-contained-html -n 8 --maxprocesses=8 $(TEST_DIR)
(e.g., add the $(SETVENV)
variable to each recipe.)