I have a Makefile which has a target to create a python virtual environment
venv:
python3 -m venv venv
... install stuff into venv ...
Now, I have several recipes which need to use the output of a command that can only be run when this virtual environment is active.
. venv/bin/activate && run_long_command
How can I set my Makefile up such that I can store the output this run_long_command
in a variable as soon as venv
target is completed, and make it available to any recipes that will need it?
Without this, I will have to run the long command as part of every recipe as the first thing it does and that's going to slow it down big time.
Another way is to make my users do make venv
separately first so that I ensure that venv
exists. Then I can do:
OUTPUT := $(shell . venv/bin/activate && run_long_command)
then I can use OUTPUT
wherever I want.
But I don't want my users to have to do this, and I don't want my targets to run slow. Any tips?
I have a Makefile which has a target to create a python virtual environment
venv:
python3 -m venv venv
... install stuff into venv ...
Now, I have several recipes which need to use the output of a command that can only be run when this virtual environment is active.
. venv/bin/activate && run_long_command
How can I set my Makefile up such that I can store the output this run_long_command
in a variable as soon as venv
target is completed, and make it available to any recipes that will need it?
Without this, I will have to run the long command as part of every recipe as the first thing it does and that's going to slow it down big time.
Another way is to make my users do make venv
separately first so that I ensure that venv
exists. Then I can do:
OUTPUT := $(shell . venv/bin/activate && run_long_command)
then I can use OUTPUT
wherever I want.
But I don't want my users to have to do this, and I don't want my targets to run slow. Any tips?
Share Improve this question asked Mar 27 at 4:55 shikhanshushikhanshu 1,5482 gold badges17 silver badges35 bronze badges1 Answer
Reset to default 2Make is not a shell and exchanging data between recipes with make variables is not very convenient, especially if you want to avoid recursive make invocations.
If, instead of storing the output of run_long_command
in a variable, you can store it in a file - say run_long_command.out
- and have the other recipes use the file instead of a variable, you could simply:
- declare
venv/bin/activate
as a prerequisite ofrun_long_command.out
, - declare
run_long_command.out
as a prerequisite of the other recipes that use it.
Example:
run_long_command.out: venv/bin/activate
. $< && run_long_command > $@
other-target: run_long_command.out
<use content of run_long_command.out>
venv/bin/activate:
python3 -m venv venv
... install stuff into venv ...
When building other-target
, if venv/bin/activate
does not exist yet the virtual environment is built. Then, if run_long_command.out
exists and is newer than venv/bin/activate
, it is considered as up to date and not re-built. It is only if it does not exist, or venv/bin/activate
has changed since its last build, that it is re-made.