Makefile to create and "activate" Python virtual environment

Viewed 2542

I'm trying to create a Python virtual environment with a Makefile and also activate it once the make command finishes to ease things for the user. Apparently, this is not possible because "a child process can not alter the parent's environment." I was wondering if there's any workaround for this. This is part of my Makefile so far: .PHONY: create-venv venv .DEFAULT_GOAL := all SHELL=/bin/bash

CPUTYPE = $(shell uname -m | sed "s/\\ /_/g")
SYSTYPE = $(shell uname -s)
BUILDDIR = build/$(SYSTYPE)-$(CPUTYPE)
VENV_NAME?=venv
VENV_DIR=$(BUILDDIR)/${VENV_NAME}
VENV_BIN=$(shell pwd)/${VENV_DIR}/bin
VENV_ACTIVATE=. ${VENV_BIN}/activate

PYTHON=${VENV_BIN}/python3

create-venv:
    test -d $(BUILDDIR) || mkdir -p $(BUILDDIR)
    which python3 || apt install -y python3 python3-pip
    test -d $(VENV_DIR) || python3 -m venv $(VENV_DIR)

venv: ${VENV_BIN}/activate
${VENV_BIN}/activate: setup.py
    test -d $(VENV_DIR) || make create-venv
    ${PYTHON} -m pip install -r requirements.txt
    touch $(VENV_BIN)/activate
    source ${VENV_BIN}/activate # <- doesn't work
    . ${VENV_BIN}/activate # <- doesn't work either
2 Answers

You can activate the environment and run a shell in the activated env:

. ${VENV_BIN}/activate && exec bash

(Please note it must be in one line to be run in one shell; exec is used to replace the shell with a new one.)

When you finish working with the environment you exit and then the Makefile is finished.

You could do something like this.

It relies on your looking at the activate script and seeing what env vars it sets, so it is totally ugly.

$(eval $(shell source $(PYTHON3_VENV)/bin/activate && echo "export PATH := $$PATH; export PYTHONHOME := $$PYTHONHOME; export VIRTUAL_ENV := $$VIRTUAL_ENV" ))
Related