From ddf5ef9e3f3f891fd6911cd97c6286a6436429b0 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Tue, 2 Jun 2015 16:23:14 +0200 Subject: docs: rst rework via pandoc Signed-off-by: Michael Grzeschik --- doc/dev_manual.rst | 1324 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1324 insertions(+) create mode 100644 doc/dev_manual.rst (limited to 'doc/dev_manual.rst') diff --git a/doc/dev_manual.rst b/doc/dev_manual.rst new file mode 100644 index 000000000..1305174c1 --- /dev/null +++ b/doc/dev_manual.rst @@ -0,0 +1,1324 @@ +PTXdist Developer’s Manual +========================== + +This chapter shows all (or most) of the details of how PTXdist works. + +|image| + +- where are the files stored that PTXdist uses when building packages + +- how patching works + +- where is PTXdist fetching a package’s runtime configuration files + from + +- how to control a package’s build stages + +- how to add new packages + +PTXdist’s directory hierarchy +----------------------------- + +Note: Referenced directories are meant relative to the PTXdist main +installation location (if not otherwise stated). If not configured +differently, this main path is ``/usr/local/lib/ptxdist-2015.03.0`` + +Rule Files +~~~~~~~~~~ + +When building a single package, PTXdist needs the information on how to +handle the package, i.e. on how to get it from the source up to what the +target needs at runtime. This information is provided by a rule file per +package. + +PTXdist collects all rule files in its ``rules/`` directory. Whenever +PTXdist builds something, all these rule files are scanned at once. +These rule files are global rule files, valid for all projects. PTXdist +uses a mechanism to be able to add or replace specific rule files on a +per project base. If a ``rules/`` directory exists in the current +project, its content is scanned too. These project local rule files are +used in addition to the global rule files or – if they are using the +same name as a global rule file – **replacing** the global rule file. + +The replacing mechanism can be used to extend or adapt packages for +specific project requirements. Or it can be used for bug fixing by +backporting rule files from more recent PTXdist revisions to projects +that are stuck to an older PTXdist revision for maintenance only. + +Patch Series +~~~~~~~~~~~~ + +There are many packages in the wild that are not cross build aware. They +fail compiling some files, use wrong include paths or try to link +against host libraries. To be sucessful in the embedded world, these +types of failures must be fixed. If required, PTXdist provides such +fixes per package. They are organized in *patch series* and can be found +in the ``patches/`` directory within a subdirectory using the same name +as the package itself. + +PTXdist uses the utility ``patch`` or ``quilt`` to apply an existing +patch series after extracting the archive. So, every patch series +contains a set of patches and one ``series`` file to define the order in +which the patches must be applied. + +Note: Patches can be compressed. + +Besides the ``patches/`` directory at the main installation location, +PTXdist searches two additional locations for a patch series for the +package in question. + +One location is the project’s currently used platform directory. If the +currently used platform is located in ``configs/``, PTXdist searches in +``./configs//patches/``. + +If no patch series was found in the platform directory, the next +location PTXdist it searches for a patch series is the main project +directory in ``./patches/``. + +If both project local locations do not provide a patch series for the +specific package, PTXdist falls back to the ``patches/`` directory at +its main installation location. + +This search order can be used to use specific patch series for specific +cases. + +- platfom specific + +- project specific + +- common case + +- bug fixing + +The *bug fixing* case is used in accordance to a replacement of a rule +file. If this was done due to a backport, and the more recent PTXdist +revision does not only exchange the rule file but also the patch series, +this mechanism ensures that both relevant parts can be updated in the +project. + +Runtime Configuration +~~~~~~~~~~~~~~~~~~~~~ + +Many packages are using runtime configuration files along with their +executables and libraries. PTXdist provides default configuration files +for the most common cases. These files can be found in the +``generic/etc`` directory and they are using the same names as the ones +at runtime (and their install directory on the target side will also be +``/etc``). + +But some of these default configuration files are empty, due to the +absence of a common case. The project must provide replacements of these +files with a more useful content in every case where the (empty) default +one does not meet the target’s requirements. + +PTXdist first searches the project local ``./projectroot/etc`` directory +for a specific configuration file and falls back to use the default one +if none exists locally. + +A popular example is the configuration file ``/etc/fstab``. The default +one coming with PTXdist works for the most common cases. But if our +project requires a special setup, we can just copy the default one to +the local ``./projectroot/etc/fstab``, modify it and we are done. The +next time PTXdist builds the root filesystem it will use the local +``fstab`` instead of the global (default) one. + +Adding new Packages +------------------- + +PTXdist provides a huge amount of applications sufficient for the most +embedded use cases. But there is still need for some fancy new packages. +This section describes the steps and the background on how to integrate +new packages into the project. + +At first a summary about possible application types which PTXdist can +handle: + +- **host type**: This kind of package is built to run on the build + host. Most of the time such a package is needed if another + target-relevant package needs to generate some data. For example the + *glib* package depends on its own to create some data. But if it is + compiled for the target, it can’t do so. That’s why a host glib + package is required to provide these utilities runnable on the build + host. It sounds strange to build a host package, even if on the build + host such utilities are already installed. But this way ensures that + there are no dependencies regarding the build host system. + +- **target type**: This kind of package is built for the target. + +- **cross type**: This kind of package is built for the build host, but + creates architecture specific data for the target. + +- **klibc type**: This kind of package is built against klibc to be + part of an initramfs for the target. + +- **src-autoconf-prog**: This kind of package is built for the target. + It is intended for development, as it does not handle a released + archive but a plain source project instead. Creating such a package + will also create a small autotools based source template project on + demand to give the developer an easy point to start. This template is + prepared to build a single executable program. + +- **src-autoconf-lib**: This kind of package is built for the target. + It is intended for development, as it does not handle a released + archive but a plain source project instead. Creating such a package + will also create a small autotools/libtool based source template + project on demand to give the developer an easy point to start. This + template is prepared to build a single shared library. For further + details refer section + [adding:sub:`s`\ rc\ :sub:`a`\ utoconf\ :sub:`l`\ ib] + +- **src-autoconf-proglib**: This kind of package is built for the + target. It is intended for development, as it does not handle a + released archive but a plain source project instead. Creating such a + package will also create a small autotools/libtool based template + project on demand to give the developer an easy point to start. This + template is prepared to build a single shared library and a single + executable program. The program will be linked against the shared + library. + +- **file**: This kind of package is intended to add a few simple files + into the build process. We assume these files do not need any + processing, they are ready to use and must only be present in the + build process or at runtime (HTML files for example). Refer to the + section [chap:adding:sub:`f`\ iles] for further details on how to use + it. + +- **src-make-prog**: This kind of package is built for the target. It’s + intended for development, as it does not handle a released archive + but a plain source project instead. Creating such a package will also + create a simple makefile-based template project the developer can use + as a starting point for development. + +- **src-cmake-prog**: This kind of package is built for the target. + It’s intended for developments based on the *cmake* buildsystem. + Various projects are using *cmake* instead of *make* and can be built + with this package type. PTXdist will prepare it to compile sources in + accordance to the target libraries and their settings. Creating such + a package will also create a simple template project to be used as a + starting point for development. + +- **src-qmake-prog**: This kind of package is built for the target. + It’s intended for developments based on the *qmake* buildsystem. If + the developer is going to develop a QT based application, this rule + is prepared to compile sources in accordance to the target libraries + and their settings. Creating such a package will also create a simple + template project to be used as a starting point for development. + +- **font**: This package is a helper to add X font files to the root + filesystem. This package does not create an additional IPKG, instead + it adds the font to the existing font IPGK. This includes the + generation of the directory index files, required by the Xorg + framework to recognize the font file. + +- **src-linux-driver**: This kind of package builds an out of tree + kernel driver. It also creates a driver template to give the + developer an easy point to start. + +Rule File Creation +~~~~~~~~~~~~~~~~~~ + +To create such a new package, we create a project local ``rules/`` +directory first. Then we run + +:: + + $ ptxdist newpackage |\textless{}package type\textgreater{}| + +If we omit the <``package type``\ >, PTXdist will list all available +package types. + +In our first example, we want to add a new target type archive package. +When running the + +:: + + $ ptxdist newpackage target + +command, PTXdist asks a few questions about this package. This +information is the basic data PTXdist must know about the package. + +:: + + ptxdist: creating a new 'target' package: + + ptxdist: enter package name.......: foo + ptxdist: enter version number.....: 1.1.0 + ptxdist: enter URL of basedir.....: http://www.foo.com/download/src + ptxdist: enter suffix.............: tar.gz + ptxdist: enter package author.....: My Name + ptxdist: enter package section....: project_specific + +What we have to answer: + +- **package name**: As this kind of package handles a source archive, + the correct answer here is the basename of the archive’s file name. + If its full name is ``foo-1.1.0.tar.gz``, then ``foo`` is the + basename to enter here. + +- **version number**: Most source archives are using a release or + version number in their file name. If its full name is + ``foo-1.1.0.tar.gz``, then ``1.1.0`` is the version number to enter + here. + +- **URL of basedir**: This URL tells PTXdist where to download the + source archive from the web (if not already done). If the full URL to + download the archive is + ``http://www.foo.com/download/src/foo-1.1.0.tar.gz``, the basedir + part ``http://www.foo.com/download/src`` is to be entered here. + +- **suffix**: Archives are using various formats for distribution. + PTXdist uses the *suffix* entry to select the matching extraction + tool. If the archive’s full name is ``foo-1.1.0.tar.gz``, then + ``tar.gz`` is the suffix to enter here. + +- **package author**: If we intend to contribute this new package to + PTXdist mainline, we should add our name here. This name will be used + in the copyright note of the rule file and will also be added to the + generated ipkg. When you run ``ptxdist setup`` prior to this call, + you can enter your name and your email address, so PTXdist will use + it as the default (very handy if you intend to add many new + packages). + +- **package section**: We can enter here the menu section name where + our new package menu entry should be listed. In the first step we can + leave the default name unchanged. It’s a string in the menu file + only, so changing it later on is still possible. + +Make it Work +~~~~~~~~~~~~ + +Generating the rule file is only one of the required steps to get a new +package. The next steps to make it work are to check if all stages are +working as expected and to select the required parts to get them +installed in the target root filesystem. Also we must find a reasonable +location where to add our new menu entry to configure the package. + +The generated skeleton starts to add the new menu entry in the main +configure menu (if we left the section name unchanged). Running +``ptxdist menuconfig`` will show it on top of all other menus entries. + +To be able to implement and test all the other required steps for adding +a new package, we first must enable the package for building. (Fine +tuning the menu can happen later on.) + +The rule file skeleton still lacks some important information. Let’s +take a look into some of the top lines of the generated rule file +``./rules/foo.make``: + +:: + + FOO_VERSION := 1.1.0 + FOO_MD5 := + FOO := foo-$(FOO_VERSION) + FOO_SUFFIX := tar.gz + FOO_URL := http://www.foo.com/download/src/$(FOO).$(FOO_SUFFIX) + FOO_SOURCE := $(SRCDIR)/$(FOO).$(FOO_SUFFIX) + FOO_DIR := $(BUILDDIR)/$(FOO) + FOO_LICENSE := unknown + +We can find these lines with different content in most or all of the +other rule files PTXdist comes with. Up to the underline character is +always the package name and after the underline character is always +PTXdist specific. What does it mean: + +- \*\_VERSION brings in the version number of the release and is used + for the download and IPKG/OPKG package generation. + +- \*\_MD5 to be sure the correct package has been downloaded, PTXdist + checks the given MD5 sum against the archive content. If both sums do + not match, PTXdist rejects the archive and fails the currently + running build. + +- \*\_SUFFIX defines the archive type, to make PTXdist choosing the + correct extracting tool. + +- \*\_URL defines the full qualified URL into the web for download. If + alternative download locations are known, they can be listed in this + variable, delimiter character is the space. + +- \*\_DIR points to the directory this package will be build later on + by PTXdist + +- \*\_LICENSE enables the user to get a list of licenses she/he is + using in her/his project (licenses of the enabled packages). + +After enabling the menu entry, we can start to check the *get* and +*extract* stages, calling them manually one after another. + +Note: The shown commands below expect that PTXdist downloads the +archives to a global directory named ``global_src``. This is not the +default setting, but we recommend to use a global directory to share all +archives between PTXdist based projects. Advantage is every download +happens only once. Refer to the ``setup`` command PTXdist provides. + +:: + + $ ptxdist get foo + + --------------------------- + target: foo-1.1.0.tar.gz + --------------------------- + + --2009-12-21 10:54:45-- http://www.foo.com/download/src/foo-1.1.0.tar.gz + Length: 291190 (284K) [application/x-gzip] + Saving to: `/global_src/foo-1.1.0.tar.gz.XXXXOGncZA' + + 100%[======================================>] 291,190 170K/s in 1.7s + + 2009-12-21 10:54:48 (170 KB/s) - `/global_src/foo-1.1.0.tar.gz' saved [291190/291190] + +This command should start to download the source archive. If it fails, +we should check our network connection, proxy setup or if the given URL +in use is correct. + +Note: Sometimes we do not know the content of all the other variables in +the rule file. To get an idea what content a variable has, we can ask +PTXdist about it: + +:: + + $ ptxdist print FOO_URL + http://www.foo.com/download/src/foo-1.1.0.tar.gz + +The next step would be to extract the archive. But as PTXdist checks the +MD5 sum in this case, this step will fail, because the ``FOO_MD5`` +variable is still empty. Let’s fill it: + +:: + + $ md5sum /global_src/foo-1.1.0.tar.gz + 9a09840ab775a139ebb00f57a587b447 + +This string must be assigned to the FOO\_MD5 in our new ``foo.make`` +rule file: + +:: + + FOO_MD5 := 9a09840ab775a139ebb00f57a587b447 + +We are now prepared for the next step: + +:: + + $ ptxdist extract foo + + ----------------------- + target: foo.extract + ----------------------- + + extract: archive=/global_src/foo-1.1.0.tar.gz + extract: dest=/home/jbe/my_new_prj/build-target + PATCHIN: packet=foo-1.1.0 + PATCHIN: dir=/home/jbe/my_new_prj/build-target/foo-1.1.0 + PATCHIN: no patches for foo-1.1.0 available + Fixing up /home/jbe/my_new_prj/build-target/foo-1.1.0/configure + finished target foo.extract + +In this example we expect an autotoolized source package. E.g. to +prepare the build, the archive comes with a ``configure`` script. This +is the default case for PTXdist. So, there is no need to modify the rule +file and we can simply run: + +:: + + $ ptxdist prepare foo + + ----------------------- + target: foo.prepare + ----------------------- + + [...] + + checking build system type... i686-host-linux-gnu + checking host system type... |\ptxdistCompilerName{}| + checking whether to enable maintainer-specific portions of Makefiles... no + checking for a BSD-compatible install... /usr/bin/install -c + checking whether build environment is sane... yes + checking for a thread-safe mkdir -p... /bin/mkdir -p + checking for gawk... gawk + checking whether make sets $(MAKE)... yes + checking for |\ptxdistCompilerName{}|-strip... |\ptxdistCompilerName{}|-strip + checking for |\ptxdistCompilerName{}|-gcc... |\ptxdistCompilerName{}|-gcc + checking for C compiler default output file name... a.out + + [...] + + configure: creating ./config.status + config.status: creating Makefile + config.status: creating ppa_protocol/Makefile + config.status: creating config.h + config.status: executing depfiles commands + finished target foo.prepare + +At this stage things can fail: + +- A wrong or no MD5 sum was given + +- The ``configure`` script is not cross compile aware + +- The package depends on external components (libraries for example) + +| If the ``configure`` script is not cross compile aware, we are out of + luck. We must patch the source archive in this case to make it work. + Refer to section [sect:configure:sub:`r`\ ebuild] on how to use + PTXdist’s features to simplify this task. +| If the package depends on external components, these components might + be already part of PTXdist. In this case we just have to add this + dependency into the menu file and we are done. But if PTXdist cannot + fulfill this dependency, we also must add it as a separate package + first. + +If the *prepare* stage has finished successfully, the next step is to +compile the package. + +:: + + $ ptxdist compile foo + + ----------------------- + target: foo.compile + ----------------------- + + make[1]: Entering directory `/home/jbe/my_new_prj/build-target/foo-1.1.0' + make all-recursive + make[2]: Entering directory `/home/jbe/my_new_prj/build-target/foo-1.1.0' + make[3]: Entering directory `/home/jbe/my_new_prj/build-target/foo-1.1.0' + + [...] + + make[3]: Leaving directory `/home/jbe/my_new_prj/build-target/foo-1.1.0' + make[2]: Leaving directory `/home/jbe/my_new_prj/build-target/foo-1.1.0' + make[1]: Leaving directory `/home/jbe/my_new_prj/build-target/foo-1.1.0' + finished target foo.compile + +At this stage things can fail: + +- The build system is not cross compile aware (it tries to execute just + created target binaries for example) + +- The package depends on external components (libraries for example) + not detected by ``configure`` + +- Sources are ignoring the endianess of some architectures or using + header files from the build host system (from ``/usr/include`` for + example) + +- The linker uses libraries from the build host system (from + ``/usr/lib`` for example) by accident + +In all of these cases we must patch the sources to make them work. Refer +to section [sect:patching:sub:`p`\ ackages] on how to use PTXdist’s +features to simplify this task. + +In this example we expect the best case: Everything went fine, even for +cross compiling. So, we can continue with the next stage: *install* + +:: + + $ ptxdist install foo + + ----------------------- + target: foo.install + ----------------------- + + make[1]: Entering directory `/home/jbe/my_new_prj/build-target/foo-1.1.0' + make[2]: Entering directory `/home/jbe/my_new_prj/build-target/foo-1.1.0' + make[3]: Entering directory `/home/jbe/my_new_prj/build-target/foo-1.1.0' + test -z "/usr/bin" || /bin/mkdir -p "/home/jbe/my_new_prj/build-target/foo-1.1.0/usr/bin" + /usr/bin/install -c 'foo' '/home/jbe/my_new_prj/build-target/foo-1.1.0/usr/bin/foo' + make[3]: Leaving directory `/home/jbe/my_new_prj/build-target/foo-1.1.0' + make[2]: Leaving directory `/home/jbe/my_new_prj/build-target/foo-1.1.0' + make[1]: Leaving directory `/home/jbe/my_new_prj/build-target/foo-1.1.0' + finished target foo.install + + ---------------------------- + target: foo.install.post + ---------------------------- + + finished target foo.install.post + +This *install* stage does not install anything to the target root +filesystem. It is mostly intended to install libraries and header files +other programs should link against later on. + +The last stage – *targetinstall* – is the one that defines the package’s +components to be forwarded to the target’s root filesystem. Due to the +absence of a generic way, this is the task of the developer. So, at this +point of time we must run our favourite editor again and modify our new +rule file ``./rules/foo.make``. + +The skeleton for the *targetinstall* stage looks like this: + +:: + + # ---------------------------------------------------------------------------- + # Target-Install + # ---------------------------------------------------------------------------- + + $(STATEDIR)/foo.targetinstall: + @$(call targetinfo) + + @$(call install_init, foo) + @$(call install_fixup, foo,PACKAGE,foo) + @$(call install_fixup, foo,PRIORITY,optional) + @$(call install_fixup, foo,VERSION,$(FOO_VERSION)) + @$(call install_fixup, foo,SECTION,base) + @$(call install_fixup, foo,AUTHOR,"My Name ") + @$(call install_fixup, foo,DEPENDS,) + @$(call install_fixup, foo,DESCRIPTION,missing) + + @$call install_copy, foo, 0, 0, 0755, $(FOO_DIR)/foobar, /dev/null) + + @$(call install_finish, foo) + @$(call touch) + +The “header” of this stage defines some information IPKG needs. The +important part that we must modify is the call to the ``install_copy`` +macro (refer to section [sect:reference:sub:`m`\ acros] for more details +about this kind of macros). This call instructs PTXdist to include the +given file (with PID, UID and permissions) into the IPKG, which means to +install this file to the target’s root filesystem. + +From the previous *install* stage we know this package installs an +executable called ``foo`` to location ``/usr/bin``. We can do the same +for our target by changing the *install\_copy* line to: + +:: + + @$(call install_copy, foo, 0, 0, 0755, $(FOO_DIR)/foo, /usr/bin/foo) + +To check it, we just run: + +:: + + $ ptxdist targetinstall foo + + ----------------------------- + target: foo.targetinstall + ----------------------------- + + install_init: preparing for image creation... + install_init: @ARCH@ -> i386 ... done + install_init: preinst not available + install_init: postinst not available + install_init: prerm not available + install_init: postrm not available + install_fixup: @PACKAGE@ -> foo ... done. + install_fixup: @PRIORITY@ -> optional ... done. + install_fixup: @VERSION@ -> 1.1.0 ... done. + install_fixup: @SECTION@ -> base ... done. + install_fixup: @AUTHOR@ -> "My Name " ... done. + install_fixup: @DESCRIPTION@ -> missing ... done. + install_copy: + src=/home/jbe/my_new_prj/build-target/foo-1.1.0/foo + dst=/usr/bin/foo + owner=0 + group=0 + permissions=0755 + xpkg_finish: collecting license (unknown) ... done. + xpkg_finish: creating ipkg package ... done. + finished target foo.targetinstall + + ---------------------------------- + target: foo.targetinstall.post + ---------------------------------- + + finished target foo.targetinstall.post + +After this command, the target’s root filesystem contains a file called +``/usr/bin/foo`` owned by root, its group is also root and everyone has +execution permissions, but only the user root has write permissions. + +| One last task of this port is still open: A reasonable location for + the new menu entry in PTXdist’s menu hierarchy. PTXdist arranges its + menus on the meaning of each package. Is it a network related tool? Or + a scripting language? Or a graphical application? +| Each of these global meanings have their own submenu, where we can add + our new entry to. We just have to edit the head of our new menu file + ``./rules/foo.in`` to add it to a specific global menu. If our new + package is a network related tool, the head of the menu file should + look like: + +:: + + ## SECTION=networking + +We can grep through the other menu files from the PTXdist main +installation ``rules/`` directory to get an idea what section names are +available: + +:: + + rules/ @\$@ find . -name \*.in | xargs grep "## SECTION" + ./acpid.in:## SECTION=shell_and_console + ./alsa-lib.in:## SECTION=system_libraries + ./alsa-utils.in:## SECTION=multimedia_sound + ./apache2.in:## SECTION=networking + ./apache2_mod_python.in:## SECTION=networking + [...] + ./klibc-module-init-tools.in:## SECTION=initramfs + ./xkeyboard-config.in:## SECTION=multimedia_xorg_data + ./xorg-app-xev.in:## SECTION=multimedia_xorg_app + ./xorg-app-xrandr.in:## SECTION=multimedia_xorg_app + ./host-eggdbus.in:## SECTION=hosttools_noprompt + ./libssh2.in:## SECTION=networking + +Porting a new package to PTXdist is finished now. + +To check it right away, we simply run these two commands: + +:: + + $ ptxdist clean foo + rm -rf /home/jbe/my_new_prj/state/foo.* + rm -rf /home/jbe/my_new_prj/packages/foo_* + rm -rf /home/jbe/my_new_prj/build-target/foo-1.1.0 + $ ptxdist targetinstall foo + + [...] + +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 [sect:foo:sub:`e`\ xample]) 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_AUTOCONF`` as the list of parameters to +be given to ``configure``. + +Currently this variable is commented out and defined to: + +:: + + # FOO_AUTOCONF := $(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_AUTOCONF := $(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_AUTOCONF + --prefix=/usr --sysconfdir=/etc --host=|\ptxdistCompilerName{}| --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 an 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 + +Note: To extend the base name by a suboption name as a trailing +component gives PTXdist the ability to detect a change in the package’s +settings to force its rebuild. + +To make usage of the new menu entries, we must check them in the rule +file and add the correct parameters: + +:: + + # + # autoconf + # + FOO_AUTOCONF := $(CROSS_AUTOCONF_USR) + + ifdef PTXCONF_FOO_DEBUG + FOO_AUTOCONF += --enable-debug + else + FOO_AUTOCONF += --disable-debug + endif + + ifdef PTXCONF_FOO_BAR + FOO_AUTOCONF += --with-bar + else + FOO_AUTOCONF += --without-bar + endif + +Please note the trailing ``PTXCONF_`` for each define. While Kconfig is +using ``FOO_BAR``, the rule file must use ``PTXCONF_FOO_BAR`` instead. + +It is a good practice to 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 want**. + +Since every optional parameter adds four lines of code to the rule +files, PTXdist provides some shortcuts to handle it. Refer to section +[ref:sub:`p`\ aram\ :sub:`m`\ acros] for further details. + +With these special macros in use, the file content shown above looks +much simpler: + +:: + + # + # autoconf + # + FOO_AUTOCONF := $(CROSS_AUTOCONF_USR) \ + $(call ptx/endis, PTXCONF_FOO_DEBUG)-debug \ + $(call ptx/wwo, PTXCONF_FOO_BAR)-bar + +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 dependencies 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. + +Managing External Compile Time Dependencies on Demand +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It is good practice to add only those dependecies 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 runtime if the correspondig 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 + +Do not add these ``select`` statements to the correspondig 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 fulfil the runtime 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 runtime. + +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 Non Autotool 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 specifiy +a special *prepare* and *compile* stage. + +Such packages often have no special need for any kind of preparation. We +can omit this stage by defining this empty rule: + +:: + + $(STATEDIR)/foo.prepare: + @$(call targetinfo) + @$(call touch) + +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. To use only ``make`` instead of the autotools, we +must instruct PTXdist to not use them by defining: + +:: + + FOO_CONF_TOOL := NO + +``make`` will be called in this case with: + +``cd $(FOO_DIR) && $(FOO_MAKE_ENV) $(MAKE) $(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. + +Note: *FOO* is still the name of our example package. It must be +replaced by the real package name. + +Patching Packages +~~~~~~~~~~~~~~~~~ + +There can be various reasons why a package must be patched: + +- Package is broken for cross compile environments + +- Package is broken within a specific feature + +- Package is vulnerable and needs some fixes + +- or anything else (this case is the most common one) + +PTXdist handles patching automatically. After extracting the archive, +PTXdist checks for the existence of a patch directory with the same name +as the package. If our package’s name is ``foo-1.1.0``, PTXdist searches +for patches in: + +#. project (``./patches/foo-1.1.0``) + +#. platform (``./configs//patches/foo-1.1.0``) + +#. ptxdist (``/patches/foo-1.1.0``) + +The patches from the first location found are used. Note: Due to this +search order, a PTXdist project can replace global patches from the +PTXdist installation. This can be useful if a project sticks to a +specific PTXdist revision but fixes from a more recent revision of +PTXdist should be used. + +Creating Patches for a Package +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +PTXdist uses the utilities ``git``, *patch* or *quilt* to work with +patches or patch series. We recommend *quilt*, as it can manage patch +series in a very easy way. For this manual we assume *quilt* is +installed on the build host. + +Creating a Patch Series for a Package +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To create a patch series for the first time, we can run the following +steps. We are still using our *foo-1.1.0* example package here: + +We create a special directory for the patch series in the local project +directory: + +:: + + $ mkdir -p patches/foo-1.1.0 + +PTXdist expects a ``series`` file in the patch directory and at least +one patch. Otherwise it fails. Due to the fact that we do not have any +patch content yet, we’ll start with a dummy entry in the ``series`` file +and an empty ``patch`` file. + +:: + + $ touch patches/foo-1.1.0/dummy + $ echo dummy > patches/foo-1.1.0/series + +Next is to extract the package (if already done, we must remove it +first): + +:: + + $ ptxdist extract foo + +This will extract the archive and create a symbolic link in the build +directory pointing to our local patch directory. Working this way will +ensure that we do not lose our created patches if we enter +``ptxdist clean foo`` by accident. In our case the patches are still +present in ``patches/foo-1.1.0`` and can be used the next time we +extract the package again. + +All we have to do now is to do the modification we need to make the +package work. We change into the build directory and use *quilt* to +create new patches, add files to respective patches, modify these files +and refresh the patches to save our changes. + +We recommend this way when modifying source files. But this way is +improper when an autotools based buildsystem itself needs modifications. +Refer to section [sect:configure:sub:`r`\ ebuild] on how PTXdist can +handle this special task. + +Adding more Patches to a Package +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If we want to add more patches to an already patched package, we can use +nearly the same way as creating patches for the first time. But if the +patch series comes from the PTXdist main installation, we do not have +write permissions to these directories (do NEVER work on the main +installation directories, NEVER, NEVER, NEVER). Due to the search order +in which PTXdist searches for patches for a specific package, we can +copy the global patch series to our local project directory. Now we have +the permissions to add more patches or modify the existing ones. Also +*quilt* is our friend here to manage the patch series. + +If we think that our new patches are valuable also for others, or they +fix an error, it could be a good idea to send these patches to PTXdist +mainline. + +Modifying Autotoolized Packages +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Autotoolized packages are very picky when automatically generated files +get patched. The patch order is very important in this case and +sometimes it even fails and nowbody knows why. + +To improve a package’s autotools-based build system, PTXdist comes with +its own project local autotools to regenerate the autotools template +files, instead of patching them. With this feature, only the template +files must be patched, the required ``configure`` script and the +``Makefile.in`` files are regenerated in the final stages of the +*prepare* step. + +This feature works like the regular patching mechanism. The only +difference is the additional ``autogen.sh`` file in the patch directory. +If it exists and has execution permissions, it will be called after the +package was patched (while the *extract* stage is running). + +Its content depends on developer needs; for the most simple case the +content can be: + +:: + + #!/bin/bash + + aclocal $ACLOCAL_FLAGS + + libtoolize \ + --force \ + --copy + + autoreconf \ + --force \ + --install \ + --warnings=cross \ + --warnings=syntax \ + --warnings=obsolete \ + --warnings=unsupported + +Note: In this way not yet autotoolized package can be autotoolized. We +just have to add the common autotool template files (``configure.ac`` +and ``Makefile.am`` for example) via a patch series to the package +source and the ``autogen.sh`` to the patch directory. + +Adding binary only Files +------------------------ + +Sometimes a few binary files have to be added into the root filesystem. +Or - to be more precise - some files, that do not need to be built in +any way. + +On the other hand, sometimes files should be included that are not +covered by any open source license and so, should not be shipped in the +source code format. + +PTXdist provides more than one way to add such type of data files to the +root filesystem it creates. The examples in this chapter refer our +generic board support package. It comes with an example how to add +binary only files into PTXdist’s build mechanism. + +Old style - single files +~~~~~~~~~~~~~~~~~~~~~~~~ + +The old style to add a simple file is present in PTXdist since its early +days: Just use the ``install_copy`` macro in the *targetinstall* stage +in your own customized rules file. + +:: + + @$(call install_copy, binary_example, 0, 0, 0644, \ + $(PTXDIST_WORKSPACE)/local_src/binary_example/ptx_logo.png, \ + /example/ptx_logo.png) + +The example above is from the file ``rules/binary_inst.make`` from +Pengutronix’s generic BSP. It copies the file ``ptx_logo.png`` from +within the BSP’s directory ``local_src/binary_example`` to target’s root +filesystem. Refer [ref:sub:`i`\ nstall\ :sub:`c`\ opy] for further +information about using the ``install_copy`` macro. + +The disadvantage of this method is: If we want to install more than one +file, we need one call to the ``install_copy`` macro per file. This is +even harder if not only a set of files is to be installed, but a whole +directory tree with files instead. + +New style - using archives +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If a whole tree of files is to be installed, working with a *tar* based +archive could make life easier. In this case the archive itself provides +all the required information the files are needing to be installed in a +correct manner: + +- the file itself and its name + +- the directory structure and the final location of every file in this + structure + +- user and group ID on a per file base + +:: + + @$(call install_archive, binary_example, -, -, \ + $(PTXDIST_WORKSPACE)/local_src/archive_example/pictures.tgz, \ + /) + +The example shown above is from the file ``rules/binary_inst.make`` from +Pengutronix’s generic BSP. It extracts the archive ``pictures.tgz`` from +within the BSP’s directory ``local_src/archive_example`` to target’s +root filesystem. Refer [ref:sub:`i`\ nstall\ :sub:`a`\ rchive] for +further information about using the ``install_archive`` macro. + +Using an archive can be usefull to install parts of the root filesystem +that are not covered by any open source license. Its possible to ship +the binaries within the regular BSP, without the need for their sources. +However it is possible for the customer to re-create everything required +from the BSP to get their target up and running again. + +Another use case for the archive method could be the support for +different development teams. One team provides a software component in +the archive format, the other team does not need to build it but can use +it in the same way than every other software component. + +Creating a Rules File +~~~~~~~~~~~~~~~~~~~~~ + +To get a rules and menu file we can copy the one from the generic BSP, +or we let PTXdist create them for us. + +:: + + $ ptxdist newpackage file + + ptxdist: creating a new 'file' package: + + ptxdist: enter package name.......: my_binfiles + ptxdist: enter version number.....: 1 + ptxdist: enter package author.....: Juergen Borleis + ptxdist: enter package section....: rootfs + +Now two new files are present in the BSP: + +#. ``rules/my_binfiles.in`` The template for the menu + +#. ``rules/my_binfiles.make`` The rules template + +Both files now must be customized to meet our requirements. Due to the +answer *rootfs* to the “``enter package section``” question, we will +find the new menu entry in: + +:: + + Root Filesystem ---> + < > my_binfiles (NEW) + +Enabling this new entry will also run our stages in +``rules/my_binfiles.make`` the next time we enter: + +:: + + $ ptxdist go + -- cgit v1.2.3