4.3. Advanced Rule Files
The previous example on how to create a rule file sometimes works as shown above. But most of the time source archives are not that simple. In this section we want to give the user a more detailed selection how the package will be built.
Adding Static Configure Parameters
The configure
scripts of various source archives provide additional
parameters to enable or disable features, or to configure them in a
specific way.
We assume the configure
script of our foo
example (refer to
section Rule File Creation) supports two additional parameters:
–enable-debug: Make the program more noisy. It’s disabled by default.
–with-bar: Also build the special executable bar. Building this executable is also disabled by default.
We now want to forward these options to the configure
script when it
runs in the prepare stage. To do so, we must again open the rule file
with our favourite editor and navigate to the prepare stage entry.
PTXdist uses the variable FOO_CONF_OPT
as the list of parameters to
be given to configure
.
Currently this variable is commented out and defined to:
# FOO_CONF_OPT := $(CROSS_AUTOCONF_USR)
The variable CROSS_AUTOCONF_USR
is predefined by PTXdist and
contains all basic parameters to instruct configure
to prepare for a
cross compile environment.
To use the two additional mentioned configure
parameters, we comment
in this line and supplement this expression as follows:
FOO_CONF_OPT := \
$(CROSS_AUTOCONF_USR) \
--enable-debug \
--with-bar
Note
We recommend to use this format with each parameter on a line of its own. This format is easier to read and a diff shows more exactly any change.
To do a fast check if this addition was successful, we run:
$ ptxdist print FOO_CONF_OPT
--prefix=/usr --sysconfdir=/etc --host=arm-v7a-linux-gnueabihf --build=i686-host-linux-gnu --enable-debug --with-bar
Note
It depends on the currently selected platform and its architecture what content this variable will have. The content shown above is an example for a target.
Or re-build the package with the new settings:
$ ptxdist drop foo prepare
$ ptxdist targetinstall foo
Adding Dynamic Configure Parameters
Sometimes it makes sense to add this kind of parameters on demand only;
especially a parameter like --enable-debug
. To let the user decide
if this parameter is to be used or not, we must add a menu entry. So,
let’s expand our menu. Here is its current content:
## SECTION=project_specific
config FOO
tristate
prompt "foo"
help
FIXME
We’ll add two menu entries, one for each optional parameter we want to
add on demand to the configure
parameters:
## SECTION=project_specific
config FOO
tristate
prompt "foo"
help
FIXME
if FOO
config FOO_DEBUG
bool
prompt "add debug noise"
config FOO_BAR
bool
prompt "build bar"
endif
Important
Always follow the rule to extend the base name by a suboption name as the trailing part of the variable name. This gives PTXdist the ability to detect a change in the package’s settings (via menuconfig) to force its rebuild on demand.
To make usage of the new menu entries, we must check them in the rule file and add the correct parameters:
#
# autoconf
#
FOO_CONF_OPT := \
$(CROSS_AUTOCONF_USR) \
--$(call ptx/endis, PTXCONF_FOO_DEBUG)-debug \
--$(call ptx/wwo, PTXCONF_FOO_BAR)-bar
Important
Please note the leading PTXCONF_
for each define. While Kconfig is
using FOO_BAR
, the rule file must use PTXCONF_FOO_BAR
instead.
Note
Refer Rule File Macro Reference for further
details about these special kind of option macros (e.g. ptx/...
).
It is a good practice to always add both settings, e.g. --disable-debug
even if this is the default case. Sometimes configure
tries to guess
something and the binary result might differ depending on the build
order. For example some kind of package would also build some X related
tools, if X libraries are found. In this case it depends on the build
order, if the X related tools are built or not. All the autocheck
features are problematic here. So, if we do not want configure
to
guess its settings we must disable everything we do not want.
To support this process, PTXdist supplies a helper script, located at
/path/to/ptxdist/scripts/configure-helper.py
that compares the configure
output with the settings from FOO_CONF_OPT
:
$ /opt/ptxdist-2017.06.0/scripts/configure-helper.py -p libsigrok
--- rules/libsigrok.make
+++ libsigrok-0.5.0
@@ -4,3 +4,74 @@
--libdir=/usr/lib
--build=x86_64-host-linux-gnu
--host=arm-v7a-linux-gnueabihf
+ --enable-warnings=min|max|fatal|no
+ --disable-largefile
+ --enable-all-drivers
+ --enable-agilent-dmm
[...]
+ --enable-ruby
+ --enable-java
+ --without-libserialport
+ --without-libftdi
+ --without-libusb
+ --without-librevisa
+ --without-libgpib
+ --without-libieee1284
+ --with-jni-include-path=DIR-LIST
In this example, many configure options from libsigrok (marked with +
)
are not yet present in LIBSIGROK_CONF_OPT
and must be added, possibly also
by providing more dynamic options in the package definition.
If some parts of a package are built on demand only, they must also be installed on demand only. Besides the prepare stage, we also must modify our targetinstall stage:
@$(call install_copy, foo, 0, 0, 0755, $(FOO_DIR)/foo, /usr/bin/foo)
ifdef PTXCONF_FOO_BAR
@$(call install_copy, foo, 0, 0, 0755, $(FOO_DIR)/bar, /usr/bin/bar)
endif
@$(call install_finish, foo)
@$(call touch)
Now we can play with our new menu entries and check if they are working as expected:
$ ptxdist menuconfig
$ ptxdist targetinstall foo
Whenever we change a FOO related menu entry, PTXdist should detect it and re-build the package when a new build is started.
Managing External Compile Time Dependencies
While running the prepare stage, it could happen that it fails due to a missing external dependency.
For example:
checking whether zlib exists....failed
In this example, our new package depends on the compression library
zlib. PTXdist comes with a target zlib. All we need to do in this
case is to declare that our new package foo depends on zlib. This
kind of dependency is managed in the menu file of our new package by
simply adding the select ZLIB
line. After this addition our menu
file looks like:
## SECTION=project_specific
config FOO
tristate
select ZLIB
prompt "foo"
help
FIXME
if FOO
config FOO_DEBUG
bool
prompt "add debug noise"
config FOO_BAR
bool
prompt "build bar"
endif
PTXdist now builds the zlib first and our new package thereafter.
Refer Controlling Package Dependencies in more Detail for more specific dependency description.
Managing External Compile Time Dependencies on Demand
It is good practice to add only those dependencies that are really
required for the current configuration of the package. If the package
provides the features foo and bar and its configure
provides
switches to enable/disable them independently, we can also add
dependencies on demand. Let’s assume feature foo needs the compression
library libz and bar needs the XML2 library libxml2. These
libraries are only required at run-time if the corresponding feature is
enabled. To add these dependencies on demand, the menu file looks like:
## SECTION=project_specific
config FOO
tristate
select ZLIB if FOO_FOO
select LIBXML2 if FOO_BAR
prompt "foo"
help
FIXME
if FOO
config FOO_DEBUG
bool
prompt "add debug noise"
config FOO_FOO
bool
prompt "build foo"
config FOO_BAR
bool
prompt "build bar"
endif
Important
Do not add these select
statements to the corresponding menu entry.
They must belong to the main menu entry of the package to ensure that
the calculation of the dependencies between the packages is done in a
correct manner.
Managing External Runtime Dependencies
Some packages are building all of their components and also installing them into the target’s sysroot. But only their targetinstall stage decides which parts are copied to the root filesystem. So, compiling and linking of our package will work, because everything required is found in the target’s sysroot.
In our example there is a hidden dependency to the math library
libm
. Our new package was built successfully, because the linker was
able to link our binaries against the libm
from the toolchain. But
in this case the libm
must also be available in the target’s root
filesystem to fulfill the run-time dependency: We have to force PTXdist to
install libm
. libm
is part of the glibc package, but is not
installed by default (to keep the root filesystem small). So, it does
not help to select the GLIBC
symbol, to get a libm
at run-time.
The correct solution here is to add a select LIBC_M
to our menu
file. With all the additions above it now looks like:
## SECTION=project_specific
config FOO
tristate
select ZLIB if FOO_FOO
select LIBXML2 if FOO_BAR
select LIBC_M
prompt "foo"
help
FIXME
if FOO
config FOO_DEBUG
bool
prompt "add debug noise"
config FOO_FOO
bool
prompt "build foo"
config FOO_BAR
bool
prompt "build bar"
endif
Note
There are other packages around, that do not install everything by
default. If our new package needs something special, we must take a look
into the menu of the other package how to force the required components
to be installed and add the corresponding selects
to our own menu
file. In this case it does not help to enable the required parts in our
project configuration, because this has no effect on the build order!
Managing Plain Makefile Packages
Many packages are still coming with a plain Makefile
. The user has
to adapt it to make it work in a cross compile environment as well.
PTXdist can also handle this kind of packages. We only have to specify
a special prepare and compile stage.
Such packages often have no special need for any kind of preparation. In this we must instruct PTXdist to do nothing in the prepare stage:
FOO_CONF_TOOL := NO
To compile the package, we can use make
’s feature to overwrite
variables used in the Makefile
. With this feature we can still use
the original Makefile
but with our own (cross compile) settings.
Most of the time the generic compile rule can be used, only a few
settings are required. For a well defined Makefile
it is sufficient to
set up the correct cross compile environment for the compile stage:
FOO_MAKE_ENV := $(CROSS_ENV)
make
will be called in this case with:
$(FOO_MAKE_ENV) $(MAKE) -C $(FOO_DIR) $(FOO_MAKE_OPT)
So, in the rule file only the two variables FOO_MAKE_ENV
and
FOO_MAKE_OPT
must be set, to forward the required settings to the
package’s buildsystem. If the package cannot be built in parallel, we
can also add the FOO_MAKE_PAR := NO
. YES
is the default.
Managing CMake/QMake/Meson Packages
Building packages that use cmake
, qmake
or meson
is much like
building packages with an autotools based buildsystem. We need to specify
the configuration tool:
FOO_CONF_TOOL := cmake
or
FOO_CONF_TOOL := qmake
or respectively
FOO_CONF_TOOL := meson
And provide the correct configuration options. The syntax is different so
PTXdist provides additional macros to simplify configurable features.
For cmake
the configuration options typically look like this:
FOO_CONF_OPT := \
$(CROSS_CMAKE_USR) \
-DBUILD_TESTS:BOOL=OFF \
-DENABLE_BAR:BOOL=$(call ptx/onoff, PTXCONF_FOO_BAR)
For qmake
the configuration options typically look like this:
FOO_CONF_OPT := \
$(CROSS_QMAKE_OPT) \
PREFIX=/usr
And for meson
the configuration options typically look like this:
FOO_CONF_OPT := \
$(CROSS_MESON_USR) \
-Dbar=$(call ptx/truefalse,PTXCONF_FOO_BAR)
Please note that currently only host and target cmake
/meson
packages
and only target qmake
packages are supported.
Managing Python Packages
As with any other package, the correct configuration tool must be selected for Python packages:
FOO_CONF_TOOL := python
Note
For Python3 packages the value must be python3
.
No Makefiles are used when building Python packages so the usual make
and make install
for the compile and install stages cannot be used.
PTXdist will call python setup.py build
and python setup.py install
instead.
Note
FOO is still the name of our example package. It must be replaced by the real package name.
Managing Cargo Packages
As with any other package, the correct configuration tool must be selected for Cargo packages:
FOO_CONF_TOOL := cargo
Additional cargo options can be added to the compile options like this:
FOO_MAKE_OPT := \
$(CROSS_CARGO_OPT) \
--features ...
Cargo wants to manage its own dependencies. PTXdist wants to manage all
downloads. To make this work, PTXdist must be aware of all cargo
dependencies. To make this possible, the package must contain a
Cargo.lock
file.
For new packages or whenever the Cargo.lock
file changes, ptxdist
cargosync foo
must be called. This creates (or updates)
foo.cargo.make
. It is placed in the same directory as foo.make
.
This introduces all dependencies from Cargo.lock
as additional sources
for the package.
Finally, PTXdist builds all cargo packages with --frozen
to ensure that
the exact same versions are used and nothing is downloaded in the compile
stage.