Integration with build systems written in Python¶
Besides the build systems commonly used by Python packages there are a few build systems written in Python and requiring the packages to script them in Python. This makes it necessary to use a proper Python eclass in order to declare their compatibility with Python versions.
Meson¶
Meson build system is a fairly recent addition. While it is written in Python, its scripts use a custom Python-agnostic script language. Hence, it can be treated as an arbitrary external tool and does not need any Python eclass.
SCons¶
SCons has gained Python 3 support quite recently. At the same time, many old script files were written for Python 2 and fail when run via Python 3 SCons. For this reason, it is necessary to use Python eclass when using SCons.
In the simplest case when the package has no other use for Python,
it is sufficient to declare PYTHON_COMPAT
for the SCons scripts
in the package, and inherit python-any-r1
prior to scons-utils
(this happens naturally when you sort includes by eclass name).
The latter eclass takes care of setting as much as possible.
If the package has other Python components, it is necessary to account for them and use an appropriate eclass as detailed in the eclass choice chapter.
Build-time use with no extra dependencies¶
If the package either has no other Python components than SCons, or all
of them are purely build-time and have no dependencies, it is sufficient
to inherit python-any-r1
. The eclass takes care of setting
BDEPEND
along with matching python_check_deps()
.
# Copyright 1999-2020 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=7
PYTHON_COMPAT=( python3_{6,7} )
inherit python-any-r1 scons-utils toolchain-funcs
COMMIT="6e5e8a57628095d8d0c8bbb38187afb0f3a42112"
DESCRIPTION="Userspace Xbox 360 Controller driver"
HOMEPAGE="https://xboxdrv.gitlab.io"
SRC_URI="https://github.com/chewi/xboxdrv/archive/${COMMIT}.tar.gz -> ${P}.tar.gz"
S="${WORKDIR}/${PN}-${COMMIT}"
LICENSE="GPL-3"
SLOT="0"
KEYWORDS="~amd64 ~x86"
RDEPEND="
dev-libs/boost:=
dev-libs/dbus-glib
dev-libs/glib:2
sys-apps/dbus
virtual/libudev:=
virtual/libusb:1
x11-libs/libX11
"
DEPEND="
${RDEPEND}
"
BDEPEND="
dev-util/glib-utils
virtual/pkgconfig
"
src_compile() {
escons \
BUILD=custom \
CXX="$(tc-getCXX)" \
AR="$(tc-getAR)" \
RANLIB="$(tc-getRANLIB)" \
CXXFLAGS="-Wall ${CXXFLAGS}" \
LINKFLAGS="${LDFLAGS}"
}
src_install() {
dobin xboxdrv
doman doc/xboxdrv.1
dodoc AUTHORS NEWS PROTOCOL README.md TODO
}
Build-time use with extra dependencies¶
If the package has extra dependencies, you need to take care of all
dependencies yourself. This is because python_gen_any_dep
cannot
be combined.
# Copyright 1999-2020 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=7
PYTHON_COMPAT=( python3_{6,7} )
inherit python-any-r1 scons-utils toolchain-funcs
MY_P=${PN}-src-r${PV/_rc/-rc}
DESCRIPTION="A high-performance, open source, schema-free document-oriented database"
HOMEPAGE="https://www.mongodb.com"
SRC_URI="https://fastdl.mongodb.org/src/${MY_P}.tar.gz"
S="${WORKDIR}/${MY_P}"
LICENSE="Apache-2.0 SSPL-1"
SLOT="0"
KEYWORDS="~amd64"
IUSE="test +tools"
RESTRICT="!test? ( test )"
RDEPEND="acct-group/mongodb
acct-user/mongodb
>=app-arch/snappy-1.1.3
>=dev-cpp/yaml-cpp-0.6.2:=
>=dev-libs/boost-1.70:=[threads(+)]
>=dev-libs/libpcre-8.42[cxx]
app-arch/zstd
dev-libs/snowball-stemmer
net-libs/libpcap
>=sys-libs/zlib-1.2.11:="
DEPEND="${RDEPEND}
${PYTHON_DEPS}
$(python_gen_any_dep '
test? ( dev-python/pymongo[${PYTHON_USEDEP}] )
>=dev-util/scons-2.5.0[${PYTHON_USEDEP}]
dev-python/cheetah3[${PYTHON_USEDEP}]
dev-python/psutil[${PYTHON_USEDEP}]
dev-python/pyyaml[${PYTHON_USEDEP}]
virtual/python-typing[${PYTHON_USEDEP}]
')
sys-libs/ncurses:0=
sys-libs/readline:0="
PDEPEND="tools? ( >=app-admin/mongo-tools-${PV} )"
python_check_deps() {
if use test; then
python_has_version "dev-python/pymongo[${PYTHON_USEDEP}]" ||
return 1
fi
python_has_version ">=dev-util/scons-2.5.0[${PYTHON_USEDEP}]" &&
python_has_version "dev-python/cheetah3[${PYTHON_USEDEP}]" &&
python_has_version "dev-python/psutil[${PYTHON_USEDEP}]" &&
python_has_version "dev-python/pyyaml[${PYTHON_USEDEP}]" &&
python_has_version "virtual/python-typing[${PYTHON_USEDEP}]"
}
src_configure() {
scons_opts=(
CC="$(tc-getCC)"
CXX="$(tc-getCXX)"
--disable-warnings-as-errors
--use-system-boost
--use-system-pcre
--use-system-snappy
--use-system-stemmer
--use-system-yaml
--use-system-zlib
--use-system-zstd
)
default
}
src_compile() {
escons "${scons_opts[@]}" core tools
}
src_test() {
"${EPYTHON}" ./buildscripts/resmoke.py --dbpathPrefix=test \
--suites core --jobs=$(makeopts_jobs) || die "Tests failed"
}
src_install() {
escons "${scons_opts[@]}" --nostrip install --prefix="${ED}"/usr
}
Single-impl package¶
If the package needs to install some Python components, and single-impl
install is appropriate, you need to combine python-single-r1
with scons-utils
. In this case, the eclass takes care of everything
needed for SCons, and you take care of everything needed for your
package.
# Copyright 1999-2020 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=5
PYTHON_COMPAT=( python2_7 )
inherit eutils python-single-r1 scons-utils toolchain-funcs
DESCRIPTION="Molecular dynamics by NMR data analysis"
HOMEPAGE="https://www.nmr-relax.com/"
SRC_URI="http://download.gna.org/relax/${P}.src.tar.bz2"
SLOT="0"
LICENSE="GPL-2"
KEYWORDS="~amd64 ~x86 ~amd64-linux ~x86-linux"
IUSE="test"
RESTRICT="!test? ( test )"
REQUIRED_USE="${PYTHON_REQUIRED_USE}"
RDEPEND="
${PYTHON_DEPS}
$(python_gen_cond_dep "
dev-python/Numdifftools[\${PYTHON_USEDEP}]
|| (
dev-python/matplotlib-python2[\${PYTHON_USEDEP}]
dev-python/matplotlib[\${PYTHON_USEDEP}]
)
|| (
dev-python/numpy-python2[\${PYTHON_USEDEP}]
dev-python/numpy[\${PYTHON_USEDEP}]
)
dev-python/wxpython:${WX_GTK_VER}[\${PYTHON_USEDEP}]
sci-chemistry/pymol[\${PYTHON_USEDEP}]
>=sci-libs/bmrblib-1.0.3[\${PYTHON_USEDEP}]
>=sci-libs/minfx-1.0.11[\${PYTHON_USEDEP}]
|| (
sci-libs/scipy-python2[\${PYTHON_USEDEP}]
sci-libs/scipy[\${PYTHON_USEDEP}]
)
")
sci-chemistry/molmol
sci-chemistry/vmd
sci-visualization/grace
sci-visualization/opendx"
DEPEND="${RDEPEND}
media-gfx/pngcrush
test? ( ${RDEPEND} )
"
src_compile() {
tc-export CC
escons
}
src_install() {
python_moduleinto ${PN}
python_domodule *
make_wrapper ${PN}-nmr "${EPYTHON} $(python_get_sitedir)/${PN}/${PN}.py $@"
}
Single-impl package with conditional Python install¶
If the runtime part of the package uses Python only conditionally,
the use is similar to a package with unconditional build-time
and conditional runtime dependency on Python. That is, build-time
dependencies, REQUIRED_USE
and pkg_setup
must be called
unconditionally.
# Copyright 1999-2020 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=7
PYTHON_COMPAT=( python3_{6,7,8} )
FORTRAN_NEEDED=fortran
FORTRAN_STANDARD=90
inherit python-single-r1 scons-utils toolchain-funcs
DESCRIPTION="Object-oriented tool suite for chemical kinetics, thermodynamics, and transport"
HOMEPAGE="https://www.cantera.org"
SRC_URI="https://github.com/Cantera/${PN}/archive/v${PV}.tar.gz -> ${P}.tar.gz"
LICENSE="BSD"
SLOT="0"
KEYWORDS="amd64 ~x86"
IUSE="fortran pch +python"
REQUIRED_USE="
${PYTHON_REQUIRED_USE}
"
RDEPEND="
python? (
${PYTHON_DEPS}
$(python_gen_cond_dep '
dev-python/numpy[${PYTHON_USEDEP}]
')
)
<sci-libs/sundials-5.1.0:0=
"
DEPEND="
${RDEPEND}
dev-cpp/eigen:3
dev-libs/boost
dev-libs/libfmt
python? (
$(python_gen_cond_dep '
dev-python/cython[${PYTHON_USEDEP}]
')
)
"
pkg_setup() {
fortran-2_pkg_setup
python-single-r1_pkg_setup
}
src_configure() {
scons_vars=(
CC="$(tc-getCC)"
CXX="$(tc-getCXX)"
cc_flags="${CXXFLAGS}"
cxx_flags="-std=c++11"
debug="no"
FORTRAN="$(tc-getFC)"
FORTRANFLAGS="${CXXFLAGS}"
optimize_flags="-Wno-inline"
renamed_shared_libraries="no"
use_pch=$(usex pch)
system_fmt="y"
system_sundials="y"
system_eigen="y"
env_vars="all"
extra_inc_dirs="/usr/include/eigen3"
)
scons_targets=(
f90_interface=$(usex fortran y n)
python2_package="none"
)
if use python ; then
scons_targets+=( python3_package="full" python3_cmd="${EPYTHON}" )
else
scons_targets+=( python3_package="none" )
fi
}
src_compile() {
escons build "${scons_vars[@]}" "${scons_targets[@]}" prefix="/usr"
}
src_test() {
escons test
}
src_install() {
escons install stage_dir="${D}" libdirname="$(get_libdir)"
python_optimize
}
Pure Python multi-impl package¶
When you are dealing with a pure Python package using SCons, it makes
sense to use plain python-r1
API. This means that SCons is going
to be called from a python_foreach_impl
loop only.
# Copyright 1999-2020 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=7
PYTHON_COMPAT=( python2_7 )
inherit fortran-2 python-r1 scons-utils toolchain-funcs
DESCRIPTION="Automated pipeline for performing Poisson-Boltzmann electrostatics calculations"
HOMEPAGE="https://www.poissonboltzmann.org/"
SRC_URI="https://github.com/Electrostatics/apbs-${PN}/releases/download/${P}/${PN}-src-${PV}.tar.gz"
SLOT="0"
LICENSE="BSD"
KEYWORDS="amd64 x86 ~amd64-linux ~x86-linux"
IUSE="opal"
REQUIRED_USE="${PYTHON_REQUIRED_USE}"
RDEPEND="${PYTHON_DEPS}
|| (
dev-python/numpy-python2[${PYTHON_USEDEP}]
dev-python/numpy[${PYTHON_USEDEP}]
)
sci-chemistry/openbabel-python[${PYTHON_USEDEP}]
opal? ( dev-python/zsi[${PYTHON_USEDEP}] )
"
DEPEND="${RDEPEND}
dev-lang/swig:0
dev-util/scons[${PYTHON_USEDEP}]"
src_prepare() {
find -type f \( -name "*.pyc" -o -name "*.pyo" \) -delete || die
eapply "${PATCHES[@]}"
eapply_user
rm -rf scons || die
python_copy_sources
}
python_configure() {
tc-export CXX
cat > "${BUILD_DIR}"/build_config.py <<-EOF || die
PREFIX="${D}/$(python_get_sitedir)/${PN}"
APBS="${EPREFIX}/usr/bin/apbs"
MAX_ATOMS=10000
BUILD_PDB2PKA=False
REBUILD_SWIG=True
EOF
}
src_configure() {
python_foreach_impl python_configure
}
src_compile() {
python_foreach_impl run_in_build_dir escons
}
python_install() {
cd "${BUILD_DIR}" || die
escons install
python_optimize
}
src_install() {
python_foreach_impl python_install
}
Hybrid python-r1 + SCons package¶
Finally, let’s consider a package that uses SCons as a build system and installs Python components independently of it. This could be e.g. a C/C++ program with separate Python bindings.
Let’s presume that the Python bindings need to be installed manually, and they support a wider target range than the build system. In this case, the any-r1 API is recommended.
# Copyright 1999-2020 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=7
PYTHON_COMPAT=( python2_7 python3_6 )
inherit python-r1 scons-utils toolchain-funcs
DESCRIPTION="GPS daemon and library for USB/serial GPS devices and GPS/mapping clients"
HOMEPAGE="https://gpsd.gitlab.io/gpsd/"
SRC_URI="mirror://nongnu/${PN}/${P}.tar.gz"
LICENSE="BSD"
SLOT="0/24"
KEYWORDS="~amd64 ~arm ~ppc ~ppc64 ~sparc ~x86"
IUSE="python"
REQUIRED_USE="
python? ( ${PYTHON_REQUIRED_USE} )"
RDEPEND="
>=net-misc/pps-tools-0.0.20120407
python? ( ${PYTHON_DEPS} )"
DEPEND="${RDEPEND}
$(python_gen_any_dep '>=dev-util/scons-2.3.0[${PYTHON_USEDEP}]' -2)
virtual/pkgconfig"
python_check_deps() {
python_has_version ">=dev-util/scons-2.3.0[${PYTHON_USEDEP}]"
}
src_configure() {
myesconsargs=(
prefix="${EPREFIX}/usr"
libdir="\$prefix/$(get_libdir)"
udevdir="$(get_udevdir)"
chrpath=False
gpsd_user=gpsd
gpsd_group=uucp
nostrip=True
manbuild=False
$(use_scons python)
)
# SConstruct uses py2 constructs
python_setup -2
}
src_compile() {
export CHRPATH=
tc-export CC CXX PKG_CONFIG
export SHLINKFLAGS=${LDFLAGS} LINKFLAGS=${LDFLAGS}
escons
}
src_install() {
DESTDIR="${D}" escons install
use python && python_foreach_impl python_domodule gps
}
waf¶
The waf build system is written in Python and bundled with the packages
using it. Therefore, it is necessary to combine waf-utils
eclass
with one of the Python eclasses.
Since SCons does not have any dependencies beside the Python interpreter, the integration is generally simple. You consider waf like any other build-time script, and use the eclass implied by other Python components in package.
Furthermore, since waf requires threading support in the Python
interpreter, it is necessary to add PYTHON_REQ_USE='threads(+)'
in
all waf packages (combined with individual package requirements if
applicable).
Build-time use¶
If waf is the only build-time Python script in the package, it is only
necessary to add PYTHON_REQ_USE
and ${PYTHON_DEPS}
to build-time
dependencies. If the package had other Python dependencies, you would
specify them instead.
# Copyright 1999-2020 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=7
PYTHON_COMPAT=( python2_7 )
PYTHON_REQ_USE='threads(+)'
NO_WAF_LIBDIR=yes
inherit python-any-r1 waf-utils
DESCRIPTION="C++ Template Unit Test Framework"
HOMEPAGE="http://mrzechonek.github.io/tut-framework/"
SRC_URI="https://github.com/mrzechonek/tut-framework/archive/${PV//./-}.tar.gz -> ${P}.tar.gz"
S="${WORKDIR}/tut-framework-${PV//./-}"
LICENSE="BSD-2"
SLOT="0"
KEYWORDS="~amd64 ~x86"
IUSE=""
BDEPEND=${PYTHON_DEPS}
Single-impl package¶
The rules for integrating simple-impl package are roughly the same
as for pure python-single-r1
use. Again, waf requires only plain
build-time ${PYTHON_DEPS}
and PYTHON_REQ_USE
.
# Copyright 1999-2020 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=6
PYTHON_COMPAT=( python2_7 )
PYTHON_REQ_USE="threads"
inherit python-single-r1 waf-utils
DESCRIPTION="An LDAP-like embedded database"
HOMEPAGE="https://ldb.samba.org/"
SRC_URI="https://www.samba.org/ftp/pub/${PN}/${P}.tar.gz"
LICENSE="LGPL-3"
SLOT="0/${PV}"
KEYWORDS="~alpha amd64 arm ~arm64 ~hppa ia64 ~mips ppc ppc64 ~s390 ~sh sparc x86"
IUSE="+ldap python"
REQUIRED_USE="python? ( ${PYTHON_REQUIRED_USE} )"
RDEPEND="!elibc_FreeBSD? ( dev-libs/libbsd )
dev-libs/popt
>=sys-libs/talloc-2.1.8[python?]
>=sys-libs/tevent-0.9.31[python(+)?]
>=sys-libs/tdb-1.3.12[python?]
python? ( ${PYTHON_DEPS} )
ldap? ( net-nds/openldap )
"
DEPEND="dev-libs/libxslt
virtual/pkgconfig
${PYTHON_DEPS}
${RDEPEND}"
WAF_BINARY="${S}/buildtools/bin/waf"
PATCHES=(
"${FILESDIR}"/${PN}-1.1.27-optional_packages.patch
"${FILESDIR}"/${P}-disable-python.patch
)
pkg_setup() {
python-single-r1_pkg_setup
}
src_configure() {
local myconf=(
$(usex ldap '' --disable-ldap)
$(usex python '' '--disable-python')
--disable-rpath
--disable-rpath-install --bundled-libraries=NONE
--with-modulesdir="${EPREFIX}"/usr/$(get_libdir)/samba
--builtin-libraries=NONE
)
waf-utils_src_configure "${myconf[@]}"
}