@@ -54,18 +54,19 @@ PRIMARY_PYTHON?=3.14
5454PYTHON_MIN_VERSION? =3.10
5555
5656# Install packages using the given package installer method.
57- # Supported are `pip` and `uv`. If uv is used, its global availability is
58- # checked. Otherwise, it is installed, either in the virtual environment or
59- # using the `PRIMARY_PYTHON`, dependent on the `VENV_ENABLED` setting. If
60- # `VENV_ENABLED` and uv is selected, uv is used to create the virtual
61- # environment.
57+ # Supported are `pip` and `uv`. When `uv` is selected, a global installation
58+ # is auto-detected and used if available. Otherwise, uv is installed in the
59+ # virtual environment or using `PRIMARY_PYTHON`, depending on the
60+ # `VENV_ENABLED` setting.
6261# Default: pip
6362PYTHON_PACKAGE_INSTALLER? =uv
6463
65- # Flag whether to use a global installed 'uv' or install
66- # it in the virtual environment.
67- # Default: false
68- MXENV_UV_GLOBAL? =true
64+ # Python version for UV to install/use when creating virtual
65+ # environments with global UV. Passed to `uv venv -p VALUE`. Supports version
66+ # specs like `3.11`, `3.14`, `cpython@3.14`. Defaults to PRIMARY_PYTHON value
67+ # for backward compatibility.
68+ # Default: $(PRIMARY_PYTHON)
69+ UV_PYTHON? =$(PRIMARY_PYTHON )
6970
7071# Flag whether to use virtual environment. If `false`, the
7172# interpreter according to `PRIMARY_PYTHON` found in `PATH` is used.
@@ -199,30 +200,57 @@ else
199200MXENV_PYTHON =$(PRIMARY_PYTHON )
200201endif
201202
202- # Determine the package installer
203+ # Determine the package installer with non-interactive flags
203204ifeq ("$(PYTHON_PACKAGE_INSTALLER ) ","uv")
204- PYTHON_PACKAGE_COMMAND =uv pip
205+ PYTHON_PACKAGE_COMMAND =uv pip --quiet --no-progress
205206else
206207PYTHON_PACKAGE_COMMAND =$(MXENV_PYTHON ) -m pip
207208endif
208209
210+ # Auto-detect global uv availability (simple existence check)
211+ ifeq ("$(PYTHON_PACKAGE_INSTALLER ) ","uv")
212+ UV_AVAILABLE: =$(shell command -v uv >/dev/null 2>&1 && echo "true" || echo "false")
213+ else
214+ UV_AVAILABLE: =false
215+ endif
216+
217+ # Determine installation strategy
218+ USE_GLOBAL_UV: =$(shell [[ "$(PYTHON_PACKAGE_INSTALLER ) " == "uv" && "$(UV_AVAILABLE ) " == "true" ]] && echo "true" || echo "false")
219+ USE_LOCAL_UV: =$(shell [[ "$(PYTHON_PACKAGE_INSTALLER ) " == "uv" && "$(UV_AVAILABLE ) " == "false" ]] && echo "true" || echo "false")
220+
221+ # Check if global UV is outdated (non-blocking warning)
222+ ifeq ("$(USE_GLOBAL_UV ) ","true")
223+ UV_OUTDATED: =$(shell uv self update --dry-run 2>&1 | grep -q "Would update" && echo "true" || echo "false")
224+ else
225+ UV_OUTDATED: =false
226+ endif
227+
209228MXENV_TARGET: =$(SENTINEL_FOLDER ) /mxenv.sentinel
210229$(MXENV_TARGET ) : $(SENTINEL )
211- ifneq ("$(PYTHON_PACKAGE_INSTALLER )$(MXENV_UV_GLOBAL ) ","uvfalse")
230+ # Validation: Check Python version if not using global uv
231+ ifneq ("$(USE_GLOBAL_UV ) ","true")
212232 @$(PRIMARY_PYTHON) -c "import sys; vi = sys.version_info; sys.exit(1 if (int(vi[0]), int(vi[1])) >= tuple(map(int, '$(PYTHON_MIN_VERSION)'.split('.'))) else 0)" \
213233 && echo "Need Python >= $(PYTHON_MIN_VERSION)" && exit 1 || :
214234else
215- @echo "Use Python $(PYTHON_MIN_VERSION) over uv "
235+ @echo "Using global uv for Python $(UV_PYTHON) "
216236endif
237+ # Validation: Check VENV_FOLDER is set if venv enabled
217238 @[[ "$(VENV_ENABLED)" == "true" && "$(VENV_FOLDER)" == "" ]] \
218239 && echo "VENV_FOLDER must be configured if VENV_ENABLED is true" && exit 1 || :
219- @[[ "$(VENV_ENABLED)$(PYTHON_PACKAGE_INSTALLER)" == "falseuv" ]] \
240+ # Validation: Check uv not used with system Python
241+ @[[ "$(VENV_ENABLED)" == "false" && "$(PYTHON_PACKAGE_INSTALLER)" == "uv" ]] \
220242 && echo "Package installer uv does not work with a global Python interpreter." && exit 1 || :
243+ # Warning: Notify if global UV is outdated
244+ ifeq ("$(UV_OUTDATED ) ","true")
245+ @echo "WARNING: A newer version of uv is available. Run 'uv self update' to upgrade."
246+ endif
247+
248+ # Create virtual environment
221249ifeq ("$(VENV_ENABLED ) ", "true")
222250ifeq ("$(VENV_CREATE ) ", "true")
223- ifeq ("$(PYTHON_PACKAGE_INSTALLER )$( MXENV_UV_GLOBAL ) ","uvtrue ")
224- @echo "Setup Python Virtual Environment using package 'uv' at '$(VENV_FOLDER)'"
225- @uv venv -p $(PRIMARY_PYTHON ) --seed $(VENV_FOLDER)
251+ ifeq ("$(USE_GLOBAL_UV ) ","true ")
252+ @echo "Setup Python Virtual Environment using global uv at '$(VENV_FOLDER)'"
253+ @uv venv --quiet --no-progress - p $(UV_PYTHON ) --seed $(VENV_FOLDER)
226254else
227255 @echo "Setup Python Virtual Environment using module 'venv' at '$(VENV_FOLDER)'"
228256 @$(PRIMARY_PYTHON) -m venv $(VENV_FOLDER)
@@ -232,10 +260,14 @@ endif
232260else
233261 @echo "Using system Python interpreter"
234262endif
235- ifeq ("$(PYTHON_PACKAGE_INSTALLER )$(MXENV_UV_GLOBAL ) ","uvfalse")
236- @echo "Install uv"
263+
264+ # Install uv locally if needed
265+ ifeq ("$(USE_LOCAL_UV ) ","true")
266+ @echo "Install uv in virtual environment"
237267 @$(MXENV_PYTHON) -m pip install uv
238268endif
269+
270+ # Install/upgrade core packages
239271 @$(PYTHON_PACKAGE_COMMAND) install -U pip setuptools wheel
240272 @echo "Install/Update MXStack Python packages"
241273 @$(PYTHON_PACKAGE_COMMAND) install -U $(MXDEV) $(MXMAKE)
0 commit comments