pip-tools.mk (3801B)
1 include gmake_python_helpers/python-vars.mk 2 3 venv_base?=virtualenvs 4 venv_pip:=$(venv_base)/pip-tools-$(PYTHON_IMPL) 5 6 # -- aggregated targets: 7 8 py-requirements: $(python_requirements_targets) # updates all *-requirements.txt files 9 py-wheels: $(python_wheel_targets) # builds wheels for all environments 10 venv: $(python_venv_targets) # installs/updates and symlinks all virtual environments 11 .PHONY: py-requirements py-wheels venv 12 13 # -- requirement file rule generator 14 15 ### from requirements.in files; example use: 16 ## create "release" environment from "release-requirements.in" file 17 # $(eval $(call PIP_COMPILE_RULE,release,release-requirements.in)) 18 ## create "dev" environment from both "release-requirements.in" and "dev-requirements.in" files 19 # $(eval $(call PIP_COMPILE_RULE,dev,release-requirements.in dev-requirements.in)) 20 21 define PIP_COMPILE_RULE = 22 $(1)-$(PYTHON_IMPL)-requirements.txt: $(2) $(PIP_COMPILE_DEP) 23 $(PIP_COMPILE) -v --annotate -o '$$@.new' $(2) 24 mv '$$@.new' '$$@' 25 $(eval $(call PY_ENVIRONMENT_RULE,$(1))) 26 endef 27 28 ### from pyproject.toml; example use: 29 ## create "release" environment non-optional dependencies 30 # $(eval $(call PYPROJECT_RULE,release,)) 31 ## create "dev" that also includes "doc" and "test" optional-dependencies 32 ## note the semicolon used to separate included extras 33 # $(eval $(call PYPROJECT_RULE,dev,doc;test)) 34 35 _comma:=, # to workaround lack of quoting or escaping in function calls 36 define PYPROJECT_RULE = 37 $(1)-$(PYTHON_IMPL)-requirements.txt: pyproject.toml $(PIP_COMPILE_DEP) 38 $(PIP_COMPILE) -v --annotate -o '$$@.new' --extra='$(subst ;,$(comma),$(2))' pyproject.toml 39 mv '$$@.new' '$$@' 40 $(eval $(call PY_ENVIRONMENT_RULE,$(1))) 41 endef 42 43 define PY_ENVIRONMENT_RULE = 44 .PRECIOUS: $(1)-$(PYTHON_IMPL)-requirements.txt 45 46 python_requirements_targets+=$(1)-$(PYTHON_IMPL)-requirements.txt 47 python_wheel_targets+=wheels/$(PYTHON_IMPL)/.done-$(1) 48 49 venv_$(1):=$(venv_base)/$(1)-$(PYTHON_IMPL) 50 venv-$(1): $(venv_base)/$(1)-$(PYTHON_IMPL)/.done 51 ln -sf '$$(venv_base)/$(1)-$(PYTHON_IMPL)' venv-$(1) 52 53 .PHONY: venv-$(1) 54 python_venv_targets+=venv-$(1) 55 endef 56 57 # The pip-tools venv is not like the others. 58 # It's created for internal use when there's no available install of pip-tools already. 59 venv-pip-tools: $(venv_pip)/bin/pip-compile $(venv_pip)/bin/wheel 60 ln -sf '$(venv_pip)' venv-pip-tools 61 62 $(venv_pip)/bin/pip-compile $(venv_pip)/bin/wheel: 63 if test -e '$(venv_pip)'; then rm -r '$(venv_pip)'; else true; fi 64 mkdir -p '$(dir $(venv_pip))' 65 $(PYTHON_VENV) '$(venv_pip)' 66 '$(venv_pip)/bin/pip' install -I pip-tools wheel 67 .PRECIOUS: $(venv_pip)/bin/pip-compile $(venv_pip)/bin/wheel 68 69 # -- rules that can be defined using patterns 70 71 wheels/$(PYTHON_IMPL)/.done-%: %-$(PYTHON_IMPL)-requirements.txt $(PIP_WHEEL_DEP) 72 mkdir -p 'wheels/$(PYTHON_IMPL)' 73 $(PIP_WHEEL) -w 'wheels/$(PYTHON_IMPL)' -r '$*-$(PYTHON_IMPL)-requirements.txt' 74 touch '$@' 75 76 $(venv_base)/%-$(PYTHON_IMPL)/.done: %-$(PYTHON_IMPL)-requirements.txt $(venv_base)/%-$(PYTHON_IMPL)/bin/pip-sync wheels/$(PYTHON_IMPL)/.done-% 77 $(venv_base)/$*-$(PYTHON_IMPL)/bin/pip-sync --no-index -f 'wheels/$(PYTHON_IMPL)' '$*-$(PYTHON_IMPL)-requirements.txt' 78 touch '$@' 79 80 $(venv_base)/%-$(PYTHON_IMPL)/bin/pip-sync: 81 if test -e '$(venv_base)/$*-$(PYTHON_IMPL)'; then rm -r '$(venv_base)/$*-$(PYTHON_IMPL)'; else true; fi 82 mkdir -p '$(dir $(venv_base)/$*-$(PYTHON_IMPL))' 83 $(PYTHON_VENV) '$(venv_base)/$*-$(PYTHON_IMPL)' 84 '$(venv_base)/$*-$(PYTHON_IMPL)/bin/pip' install -I $(PYTHON_VENV_INSTALL) 85 .PRECIOUS: $(venv_base)/$*-$(PYTHON_IMPL)/bin/pip-sync 86 87 $(venv_base)/%-$(PYTHON_IMPL)/.done: %-$(PYTHON_IMPL)-requirements.txt $(venv_base)/%-$(PYTHON_IMPL)/bin/pip-sync wheels/$(PYTHON_IMPL)/.done-% 88 $(venv_base)/$*-$(PYTHON_IMPL)/bin/pip-sync --no-index -f 'wheels/$(PYTHON_IMPL)' '$*-$(PYTHON_IMPL)-requirements.txt' 89 touch '$@' 90