394 lines
13 KiB
Makefile
394 lines
13 KiB
Makefile
# python.port.mk - This file is in the public domain.
|
|
# Xavier Santolaria <xavier@santolaria.net>
|
|
# Stuart Henderson <stu@spacehopper.org>
|
|
|
|
CATEGORIES += lang/python
|
|
|
|
# define the default versions
|
|
MODPY_DEFAULT_VERSION_2 = 2.7
|
|
MODPY_DEFAULT_VERSION_3 = 3.12
|
|
MODPY_VERSION ?= ${MODPY_DEFAULT_VERSION_3}
|
|
|
|
# If switching to a new MODPY_DEFAULT_VERSION_3, say 3.x to 3.y:
|
|
# - All ports with PLISTs that depend on the Python version number
|
|
# must be REVISION-bumped.
|
|
# - Keep xenocara/share/mk/bsd.xorg.mk PYTHON_VERSION in sync.
|
|
|
|
# verify if MODPY_VERSION found is correct
|
|
.if ${MODPY_VERSION} == "2.7"
|
|
_MODPY_SUBDIR = 2.7
|
|
.elif ${MODPY_VERSION} == "3.12"
|
|
_MODPY_SUBDIR = 3
|
|
.else
|
|
ERRORS += "Fatal: unknown or unsupported MODPY_VERSION: ${MODPY_VERSION}"
|
|
.endif
|
|
|
|
MODPY_WANTLIB = python${MODPY_VERSION}
|
|
MODPY_RUN_DEPENDS = lang/python/${_MODPY_SUBDIR}
|
|
MODPY_LIB_DEPENDS = lang/python/${_MODPY_SUBDIR}
|
|
_MODPY_BUILD_DEPENDS = lang/python/${_MODPY_SUBDIR}
|
|
MODPY_TKINTER_DEPENDS = lang/python/${_MODPY_SUBDIR},-tkinter
|
|
|
|
MODPY_MAJOR_VERSION = ${MODPY_VERSION:R}
|
|
|
|
.if ${MODPY_MAJOR_VERSION} == 2
|
|
MODPY_PY_PREFIX = py-
|
|
MODPY_PYCACHE =
|
|
MODPY_PYC_MAGIC_TAG =
|
|
MODPY_COMMENT = "@comment "
|
|
MODPY_ABI3SO =
|
|
MODPY_PYOEXTENSION = pyo
|
|
.elif ${MODPY_MAJOR_VERSION} == 3
|
|
# replace py- prefix with py3-
|
|
FULLPKGNAME ?= ${PKGNAME:S/^py-/py3-/}${FLAVOR_EXT}
|
|
MODPY_PY_PREFIX = py3-
|
|
MODPY_PYCACHE = __pycache__/
|
|
MODPY_MAJORMINOR = ${MODPY_VERSION:C/\.//g}
|
|
MODPY_PYC_MAGIC_TAG = cpython-${MODPY_MAJORMINOR}.
|
|
MODPY_COMMENT =
|
|
MODPY_ABI3SO = .abi3
|
|
MODPY_PYOEXTENSION ?= opt-1.pyc
|
|
.endif
|
|
|
|
MODPY_SETUPTOOLS ?=
|
|
MODPY_SETUPUTILS ?=
|
|
MODPY_PYBUILD ?= No
|
|
MODPY_PI ?=
|
|
|
|
# If MODPY_PYTEST_ARGS are set, or if using MODPY_PYBUILD, it implies that
|
|
# we want MODPY_PYTEST = Yes
|
|
MODPY_PYTEST_ARGS ?=
|
|
.if empty(MODPY_PYTEST_ARGS) && ${MODPY_PYBUILD:L} == no
|
|
MODPY_PYTEST ?= No
|
|
.else
|
|
MODPY_PYTEST ?= Yes
|
|
.endif
|
|
|
|
.if ${MODPY_PYTEST:L} == "yes"
|
|
MODPY_TEST_DEPENDS = ${RUN_DEPENDS}
|
|
MODPY_TEST_DEPENDS += devel/py-test
|
|
.else
|
|
MODPY_TEST_DEPENDS = ${MODPY_RUN_DEPENDS}
|
|
.endif
|
|
|
|
.if ${NO_BUILD:L} == "no"
|
|
MODPY_BUILDDEP ?= Yes
|
|
.else
|
|
MODPY_BUILDDEP ?= No
|
|
.endif
|
|
MODPY_RUNDEP ?= Yes
|
|
.if ${NO_TEST:L} == "no"
|
|
MODPY_TESTDEP ?= Yes
|
|
.else
|
|
MODPY_TESTDEP ?= No
|
|
.endif
|
|
|
|
.if ${MODPY_BUILDDEP:L} == "yes"
|
|
BUILD_DEPENDS += ${_MODPY_BUILD_DEPENDS}
|
|
.endif
|
|
|
|
.if ${MODPY_RUNDEP:L} == "yes"
|
|
RUN_DEPENDS += ${MODPY_RUN_DEPENDS}
|
|
.endif
|
|
|
|
.if ${MODPY_TESTDEP:L} == "yes"
|
|
TEST_DEPENDS += ${MODPY_TEST_DEPENDS}
|
|
.endif
|
|
|
|
_MODPY_PRE_BUILD_STEPS = :
|
|
|
|
.if ${MODPY_PYBUILD:L} == "no" && ${MODPY_MAJOR_VERSION} != 2
|
|
# not necessarily an error, but try to draw attention to it. defer printing
|
|
# the warning to fake-install where it's less likely to scroll off the screen.
|
|
_MODPY_PRE_BUILD_STEPS += ; if [ -e ${WRKSRC}/pyproject.toml ] && \
|
|
grep -q ^build-backend ${WRKSRC}/pyproject.toml; then \
|
|
(echo; echo '*** Ports with pyproject.toml should normally use MODPY_PYBUILD'; \
|
|
grep -H ^build-backend ${WRKSRC}/pyproject.toml; echo ) >> \
|
|
${WRKDIR}/.modpy-warn; \
|
|
fi
|
|
.endif
|
|
|
|
_MODPY_USE_CARGO = No
|
|
|
|
.if ${MODPY_SETUPTOOLS:L} == "yes"
|
|
. if ${MODPY_PYBUILD:L} != "no"
|
|
ERRORS += "Fatal: both MODPY_PYBUILD and MODPY_SETUPTOOLS are set. Just use MODPY_PYBUILD."
|
|
. endif
|
|
# For Python 2, setuptools provides a package locator that is required at
|
|
# runtime for pkg_resources to work, so an RDEP is needed.
|
|
# For Python 3, pkg_resources is deprecated - Python core has similar
|
|
# functionality in importlib.metadata.
|
|
# If a py3 port still needs pkg_resources, expect deprecation warnings
|
|
# at runtime, and in that case an RDEP on setuptools should be added
|
|
# manually.
|
|
. if ${MODPY_MAJOR_VERSION} == 2
|
|
MODPY_SETUPUTILS_DEPEND ?= devel/py2-setuptools
|
|
MODPY_RUN_DEPENDS += ${MODPY_SETUPUTILS_DEPEND}
|
|
. else
|
|
MODPY_SETUPUTILS_DEPEND ?= devel/py-setuptools
|
|
. endif
|
|
|
|
BUILD_DEPENDS += ${MODPY_SETUPUTILS_DEPEND}
|
|
MODPY_SETUPUTILS = Yes
|
|
|
|
# The setuptools uses test target
|
|
TEST_TARGET ?= test
|
|
_MODPY_USERBASE =
|
|
_MODPY_PRE_BUILD_STEPS += ;${MODPY_CMD} egg_info || true
|
|
.elif ${MODPY_PYBUILD:L} != no
|
|
BUILD_DEPENDS += devel/py-build \
|
|
devel/py-installer
|
|
. if ${MODPY_PYBUILD} == flit
|
|
BUILD_DEPENDS += devel/py-flit
|
|
. elif ${MODPY_PYBUILD} == flit_core
|
|
BUILD_DEPENDS += devel/py-flit_core
|
|
. elif ${MODPY_PYBUILD} == flit_scm
|
|
BUILD_DEPENDS += devel/py-flit_scm
|
|
. elif ${MODPY_PYBUILD} == hatch-vcs
|
|
BUILD_DEPENDS += devel/py-hatch-vcs
|
|
_MODPY_EXPECTED_BACKEND = hatchling
|
|
. elif ${MODPY_PYBUILD} == hatchling
|
|
BUILD_DEPENDS += devel/py-hatchling
|
|
. elif ${MODPY_PYBUILD} == jupyter_packaging
|
|
BUILD_DEPENDS += devel/py-jupyter_packaging
|
|
_MODPY_EXPECTED_BACKEND = setuptools
|
|
. elif ${MODPY_PYBUILD} == maturin
|
|
BUILD_DEPENDS += devel/maturin
|
|
MODCARGO_CARGO_BIN = maturin
|
|
_MODPY_WHEELSDIR = target/wheels
|
|
_MODPY_USE_CARGO = Yes
|
|
. elif ${MODPY_PYBUILD} == mesonpy
|
|
BUILD_DEPENDS += devel/meson-python
|
|
. elif ${MODPY_PYBUILD} == pbr
|
|
BUILD_DEPENDS += devel/py-pbr \
|
|
devel/py-setuptools \
|
|
devel/py-wheel
|
|
. elif ${MODPY_PYBUILD} == pdm
|
|
BUILD_DEPENDS += devel/py-pdm-backend
|
|
. elif ${MODPY_PYBUILD} == poetry-core
|
|
BUILD_DEPENDS += devel/py-poetry-core
|
|
_MODPY_EXPECTED_BACKEND = poetry.core
|
|
. elif ${MODPY_PYBUILD} == setuptools || \
|
|
${MODPY_PYBUILD} == setuptools_scm || \
|
|
${MODPY_PYBUILD} == setuptools-rust
|
|
BUILD_DEPENDS += devel/py-setuptools \
|
|
devel/py-wheel
|
|
_MODPY_EXPECTED_BACKEND = setuptools
|
|
. if ${MODPY_PYBUILD} == setuptools_scm
|
|
BUILD_DEPENDS += devel/py-setuptools_scm
|
|
. elif ${MODPY_PYBUILD} == setuptools-rust
|
|
BUILD_DEPENDS += devel/py-setuptools-rust
|
|
_MODPY_USE_CARGO = Yes
|
|
. endif
|
|
. elif !${MODPY_PYBUILD:L:Mother}
|
|
ERRORS += "Fatal: unknown MODPY_PYBUILD value (flit, flit_core, flit_scm, hatch-vcs, hatchling, jupyter_packaging, pbr, pdm, maturin, mesonpy, other, poetry-core, setuptools, setuptools_scm, setuptools-rust)"
|
|
. endif
|
|
_MODPY_EXPECTED_BACKEND ?= ${MODPY_PYBUILD}
|
|
_MODPY_WHEELSDIR ?= dist
|
|
. if ${_MODPY_USE_CARGO:L} == yes
|
|
MODCARGO_INSTALL ?= No
|
|
MODCARGO_TEST ?= No
|
|
MODULES += devel/cargo
|
|
. endif
|
|
.else
|
|
MODPY_SETUPUTILS = No
|
|
# Detect the case where a port is capable of building with setup.py
|
|
# via fallback to distutils, but should use py-build instead.
|
|
_MODPY_SETUPUTILS_FAKE_DIR = \
|
|
${WRKDIR}/lib/python${MODPY_VERSION}/site-packages/setuptools
|
|
_MODPY_PRE_BUILD_STEPS += \
|
|
;mkdir -p ${_MODPY_SETUPUTILS_FAKE_DIR} \
|
|
;exec 3>&1 \
|
|
;exec >${_MODPY_SETUPUTILS_FAKE_DIR}/__init__.py \
|
|
;echo 'def setup(*args, **kwargs):' \
|
|
;echo ' msg = "SecBSD ports: use MODPY_PYBUILD"' \
|
|
;echo ' raise Exception(msg)' \
|
|
;echo 'Extension = Feature = find_packages = setup' \
|
|
;exec 1>&3
|
|
_MODPY_USERBASE = ${WRKDIR}
|
|
.endif
|
|
|
|
# XXX If we run into too many problems with setuptools ports and junking
|
|
# XXX then this can be enabled, however if a "nojunk" port fails to build,
|
|
# XXX DPB will no longer junk on that node, likely resulting in running
|
|
# XXX out of disk space in /usr/local. So far it has only happened very
|
|
# XXX occasionally and a single port failure is easier to clean up, and
|
|
# XXX setuptools use is decreasing, so trying to avoid this!
|
|
#
|
|
#.if ${MODPY_SETUPTOOLS:L} == "yes" || ${MODPY_PYBUILD:Msetuptools*}
|
|
# Setuptools opportunistically picks up plugins. If it picks one up that
|
|
# uses finalize_distribution_options (usually setuptools_scm), junking
|
|
# that plugin will cause failure at the end of build.
|
|
# In the absence of a targetted means of disabling this, use a big hammer:
|
|
#DPB_PROPERTIES += nojunk
|
|
#.endif
|
|
|
|
.if ${MODPY_PI:L} == "yes"
|
|
_MODPY_EGG_NAME = ${DISTNAME:S/-${MODPY_DISTV}//}
|
|
MODPY_PI_DIR ?= ${DISTNAME:C/^([a-zA-Z0-9]).*/\1/}/${_MODPY_EGG_NAME}
|
|
SITES = ${SITE_PYPI:=${MODPY_PI_DIR}/}
|
|
HOMEPAGE ?= https://pypi.python.org/pypi/${_MODPY_EGG_NAME}
|
|
.endif
|
|
|
|
MODPY_BIN = ${LOCALBASE}/bin/python${MODPY_VERSION}
|
|
MODPY_INCDIR = ${LOCALBASE}/include/python${MODPY_VERSION}
|
|
MODPY_LIBDIR = ${LOCALBASE}/lib/python${MODPY_VERSION}
|
|
MODPY_SITEPKG = ${MODPY_LIBDIR}/site-packages
|
|
|
|
# usually setup.py but Setup.py can be found too
|
|
MODPY_SETUP ?= setup.py
|
|
|
|
# build or build_ext are commonly used
|
|
MODPY_DISTUTILS_BUILD ?= build --build-base=${WRKBUILD}
|
|
|
|
.if ${MODPY_SETUPUTILS:L} == "yes"
|
|
MODPY_DISTUTILS_INSTALL ?= install --prefix=${TRUEPREFIX} \
|
|
--root=${DESTDIR} \
|
|
--single-version-externally-managed
|
|
.else
|
|
MODPY_DISTUTILS_INSTALL ?= install --prefix=${TRUEPREFIX} \
|
|
--root=${DESTDIR}
|
|
.endif
|
|
|
|
MAKE_ENV += CC=${CC} PYTHONUSERBASE=${_MODPY_USERBASE}
|
|
CONFIGURE_ENV += PYTHON="${MODPY_BIN}"
|
|
.if ${CONFIGURE_STYLE:Mgnu}
|
|
CONFIGURE_ENV += ac_cv_prog_PYTHON="${MODPY_BIN}" \
|
|
ac_cv_path_PYTHON="${MODPY_BIN}"
|
|
.endif
|
|
|
|
_MODPY_RUNBIN = cd ${WRKSRC} && ${SETENV} ${MAKE_ENV} ${MODPY_BIN}
|
|
|
|
MODPY_CMD = cd ${WRKSRC} && ${SETENV} ${MAKE_ENV} \
|
|
${MODPY_BIN} ./${MODPY_SETUP} \
|
|
${MODPY_SETUP_ARGS}
|
|
|
|
MODPY_TEST_DIR ?= ${WRKSRC}
|
|
|
|
MODPY_TEST_CMD = cd ${MODPY_TEST_DIR} && ${SETENV} ${ALL_TEST_ENV} ${MODPY_BIN}
|
|
.if ${MODPY_PYTEST:L} == "yes"
|
|
MODPY_PYTEST_USERARGS ?=
|
|
MODPY_TEST_CMD += -m pytest ${MODPY_PYTEST_USERARGS}
|
|
MODPY_TEST_LIBDIR ?= ${WRKINST}${MODPY_SITEPKG}:${WRKSRC}/build/lib:${WRKSRC}/build/lib.openbsd-${OSREV}-${ARCH}-cpython-${MODPY_MAJORMINOR}:${WRKSRC}/lib.openbsd-${OSREV}-${ARCH}-${MODPY_VERSION}
|
|
.else
|
|
MODPY_TEST_CMD += ./${MODPY_SETUP} ${MODPY_SETUP_ARGS}
|
|
.endif
|
|
|
|
MODPY_TEST_LIBDIR ?=
|
|
MODPY_TEST_LOCALE ?= LC_CTYPE=en_US.UTF-8
|
|
TEST_ENV += ${MODPY_TEST_LOCALE}
|
|
|
|
.if !empty(MODPY_TEST_LIBDIR)
|
|
TEST_ENV += PYTHONPATH=${MODPY_TEST_LIBDIR}:lib:src
|
|
.endif
|
|
|
|
SUBST_VARS := MODPY_PYCACHE MODPY_COMMENT MODPY_ABI3SO MODPY_PYC_MAGIC_TAG \
|
|
MODPY_BIN MODPY_DISTV MODPY_VERSION \
|
|
MODPY_PY_PREFIX MODPY_PYOEXTENSION ${SUBST_VARS}
|
|
|
|
UPDATE_PLIST_ARGS += -S MODPY_PYOEXTENSION \
|
|
-I MODPY_ABI3SO -c MODPY_COMMENT -I MODPY_PYCACHE
|
|
|
|
# set MODPY_BIN for executable scripts
|
|
MODPY_BIN_ADJ = perl -pi \
|
|
-e '$$. == 1 && s|^.*env +python.*$$|\#!${MODPY_BIN}|;' \
|
|
-e '$$. == 1 && s|^.*bin/python.*$$|\#!${MODPY_BIN}|;' \
|
|
-e 'close ARGV if eof;' --
|
|
|
|
MODPY_ADJ_FILES ?=
|
|
.if !empty(MODPY_ADJ_FILES)
|
|
MODPYTHON_pre-configure += cd ${WRKSRC} && ${MODPY_BIN_ADJ} ${MODPY_ADJ_FILES}
|
|
.endif
|
|
|
|
.if ${MODPY_VERSION} == ${MODPY_DEFAULT_VERSION_2}
|
|
MODPY_COMPILEALL = ${MODPY_BIN} -m compileall
|
|
.else
|
|
MODPY_COMPILEALL = ${MODPY_BIN} -m compileall -j ${MAKE_JOBS} -s ${WRKINST} -o 0 -o 1
|
|
.endif
|
|
|
|
MODPY_TEST_TARGET =
|
|
MODPY_TEST_LINK_SO ?= No
|
|
.if ${MODPY_TEST_LINK_SO:L} == "yes" && !empty(MODPY_TEST_LIBDIR)
|
|
MODPY_TEST_SO_CMD = for _dir in ${MODPY_TEST_LIBDIR:S,:, ,g}; do \
|
|
if [ -d $${_dir} ]; then \
|
|
cd $${_dir} && \
|
|
find . -name '*.so' -type f \
|
|
-exec ln -sf $${_dir}/{} ${WRKSRC}/{} \; ;\
|
|
fi; done
|
|
MODPY_TEST_TARGET += ${MODPY_TEST_SO_CMD};
|
|
.endif
|
|
|
|
.if ${MODPY_PYBUILD:L} != no
|
|
. if ! ${MODPY_PYBUILD:Msetuptools_scm}
|
|
_MODPY_PRE_BUILD_STEPS += ; if [ -e ${WRKSRC}/pyproject.toml ] && \
|
|
grep -q '^requires.*setuptools[-_]scm' ${WRKSRC}/pyproject.toml; then \
|
|
(echo; echo '*** Port may need MODPY_PYBUILD=setuptools_scm'; \
|
|
grep -H -e ^build-backend -e '^requires.*setuptools' \
|
|
${WRKSRC}/pyproject.toml; echo ) >> ${WRKDIR}/.modpy-warn; \
|
|
fi
|
|
. endif
|
|
. if ${_MODPY_EXPECTED_BACKEND} != other
|
|
_MODPY_PRE_BUILD_STEPS += ; if [ -e ${WRKSRC}/pyproject.toml ] && \
|
|
grep '^build-backend' ${WRKSRC}/pyproject.toml | \
|
|
grep -qv ${_MODPY_EXPECTED_BACKEND}; then \
|
|
(echo; echo '*** Check MODPY_PYBUILD setting (currently "${MODPY_PYBUILD}")'; \
|
|
grep -H ^build-backend ${WRKSRC}/pyproject.toml; echo ) >> \
|
|
${WRKDIR}/.modpy-warn; \
|
|
fi
|
|
. endif
|
|
MODPY_PYBUILD_ARGS ?=
|
|
MODPY_BUILD_TARGET = ${_MODPY_PRE_BUILD_STEPS}; \
|
|
${_MODPY_RUNBIN} -sBm build -w --no-isolation ${MODPY_PYBUILD_ARGS}
|
|
MODPY_INSTALL_TARGET = \
|
|
${INSTALL_DATA_DIR} ${WRKINST}${MODPY_LIBDIR}; \
|
|
${_MODPY_RUNBIN} -m installer -d ${WRKINST} ${WRKSRC}/${_MODPY_WHEELSDIR}/*.whl
|
|
MODPY_TEST_TARGET += ${MODPY_TEST_CMD}
|
|
. if ${MODPY_PYTEST:L} == "yes"
|
|
MODPY_TEST_TARGET += ${MODPY_PYTEST_ARGS}
|
|
. endif
|
|
.else
|
|
MODPY_BUILD_TARGET = ${_MODPY_PRE_BUILD_STEPS}; \
|
|
${MODPY_CMD} ${MODPY_DISTUTILS_BUILD} ${MODPY_DISTUTILS_BUILDARGS}
|
|
MODPY_INSTALL_TARGET = \
|
|
${MODPY_CMD} ${MODPY_DISTUTILS_BUILD} ${MODPY_DISTUTILS_BUILDARGS} \
|
|
${MODPY_DISTUTILS_INSTALL} ${MODPY_DISTUTILS_INSTALLARGS}
|
|
|
|
MODPY_TEST_TARGET += ${MODPY_TEST_CMD}
|
|
. if ${MODPY_PYTEST:L} == "yes"
|
|
MODPY_TEST_TARGET += ${MODPY_PYTEST_ARGS}
|
|
. elif ${MODPY_SETUPUTILS:L} == "yes"
|
|
MODPY_TEST_TARGET += ${TEST_TARGET}
|
|
. endif
|
|
.endif
|
|
|
|
MODPY_INSTALL_TARGET += ; if [ -r ${WRKDIR}/.modpy-warn ]; then cat ${WRKDIR}/.modpy-warn; fi
|
|
|
|
.if empty(CONFIGURE_STYLE)
|
|
. if !target(do-configure) && ${_MODPY_USE_CARGO:L} == yes
|
|
do-configure:
|
|
@${MODCARGO_configure}
|
|
. endif
|
|
|
|
. if !target(do-build)
|
|
do-build:
|
|
. if ${_MODPY_USE_CARGO:L} == yes
|
|
@${MODCARGO_BUILD_TARGET}
|
|
. endif
|
|
. if ${MODPY_PYBUILD} != maturin
|
|
@${MODPY_BUILD_TARGET}
|
|
. endif
|
|
. endif
|
|
|
|
# extra documentation or scripts should be installed via post-install
|
|
. if !target(do-install)
|
|
do-install:
|
|
@${MODPY_INSTALL_TARGET}
|
|
. endif
|
|
|
|
. if !target(do-test) && \
|
|
(${MODPY_SETUPUTILS:L} == "yes" || ${MODPY_PYTEST:L} == "yes")
|
|
do-test:
|
|
@${MODPY_TEST_TARGET}
|
|
. endif
|
|
|
|
.endif
|