Sortix nightly manual
This manual documents Sortix nightly, a development build that has not been officially released. You can instead view this document in the latest official manual.
NAME
porting — guide for porting softwareSYNOPSIS
/src/ports/example/example.portDESCRIPTION
This manual documents how to port software to this operating system as packaged ports in the port(5) format.Philosophy
The ports collection is maintained according to a set of principles designed to uphold quality, keep the ports maintainable, and to enable giving back improvements to the upstream projects.Metadata
A port named example can be built along with the operating system by creating the /src/ports/example/example.port file with the meta information documented in port(5).NAME=example BUILD_LIBRARIES='libfoo libbar? libqux?' VERSION=1.2.3 DISTNAME=$NAME-$VERSION COMPRESSION=tar.gz ARCHIVE=$DISTNAME.$COMPRESSION SHA256SUM=b8d67e37894726413f0d180b2c5a8369b02d4a2961bb50d2a8ab6f553f430976 UPSTREAM_SITE=https://example.com/pub/example UPSTREAM_ARCHIVE=$ARCHIVE BUILD_SYSTEM=configure LICENSE=example DEVELOPMENT=true
Building
The port can be finished by repeatedly trying to build it and iteratively fixing any issues that occur per development(7):cd /src make clean-sysroot make PACKAGES='example!'
rm -f repository/*/example.tix.tar.xz # delete stale binary package rm -f repository/*/example.version # optional make clean-repository # or: remove all binary packages
Finishing
The port can be finished by testing it thoroughly and reviewing the details.make clean-sysroot make PACKAGES='example!!'
du -h repository/*/example.tix.tar.xz tar -t -f repository/*/example.tix.tar.xz
Upgrading ports
Ports can be upgraded by switching the port back in development mode with a updated version number and checksum.make available-ports # Search for newly available versions of ports make upgrade-ports PACKAGES=example # Update example port make PACKAGES='example!!' # Find the new sha256sum # Verify the new sha256sum is authentic. make PACKAGES='example!!' # Any old patches may fail to apply. find ports/example -name '*.rej' -o -name '*.orig' make PACKAGES='example!!' # Regenerate patches on a successful build. sed -E '/^DEVELOPMENT=true$/d' ports/example/example.port make PACKAGES='example!!' # Final build and testing.
EXAMPLES
This section describes common situations and portability issues and how to resolve them.config.sub
The config.sub file parses the build/host/target triplet and is duplicated into all software using autoconf. If the port ships a version older than 2015-08-20, configure will fail to parse the operating system:checking host system type... Invalid configuration `x86_64-sortix': system `sortix' not recognized
| -aos* | -aros* | -cloudabi* | -sortix* \
Configure
If the configure script fails, then autoconf configure scripts produce a config.log file which contain useful diagnostic information, such as which programs were compiled to check for a particular feature and what happened when they were compiled, linked, and executed. This information can be used to locate the relevant logic in the configure script.Non-verbose make
Some ports default to a non-verbose make mode that doesn't show the commands being run. Ports should show the commands invoked by make, which can done with an environment variable assignment V=1 which can be made permanent using MAKE_VARS=V=1.Patching
The build may fail or warn for various reasons which needs to be patched, or the port may need extra support for the operating system. The sources become writable once the port is in development mode and can simply be edited to fix the problem. The patch files are regenerated whenever the port builds successfully.// PATCH: Use foo instead because bar doesn't work yet. #ifdef __sortix__ foo(); #else bar(); #endif
#if __has_include(<foo.h>) #include <foo.h> #endif
Configuration files
Configuration files in /etc belongs to the system administrator and must not be installed by ports, as local changes will otherwise be undone whenever the port is upgraded.Portability issues
The port might not be portable and requires patching. Often the port uses a non-standard interface when a standard interface is available and should be used instead. Other times the operating system is missing functionality which should ideally be implemented before proceeding with the port, or perhaps the absence can be worked around.libtool .la files
Libraries using libtool may install /lib/*.la files which are unnecessary and contain absolute paths which cause cross-compilation to fail. Ports should never install such files and instead rely on pkg-config(1) for locating dependencies.POST_INSTALL=tix-eradicate-libtool-la
Post-install command
Ports may install files with an unconventional directory layout or may install unnecessary large files. Ideally the makefile should be patched to install correctly in the first place, but if doing so is impractical, then a post-install command can be used to fix up the installation in the DESTDIR before the binary package is created. An executable example.post-install script can be placed next to the example.port files:POST_INSTALL=../example.post-install
#!/bin/sh set -e [ -n "$TIX_INSTALL_DIR" ] mv "$TIX_INSTALL_DIR$PREFIX/share/foo" "$TIX_INSTALL_DIR$PREFIX/share/bar"
Splitting into multiple ports
Upstream releases might have multiple parts, such as a program that also comes with a library, which should be split into multiple ports whenever reasonable.Gnulib
Gnulib is a GNU portability layer that has three purposes:- Providing fallback implementations of missing standard library interfaces.
- Replacing buggy implementations of standard library interfaces.
- Sharing common utility functions between projects.
- The replacement implementations tend to be non-portable and one is supposed to modify the source code to rely on private standard library details that may be subject to change.
- Gnulib is highly forked by design and adding support for new operating systems needs to be done upstream and it may take years for the support to reach new downstream releases.
- Gnulib has assumed the worst in the past when cross-compiling, assuming unknown operating systems are buggy, injecting a non-portable replacement that doesn't compile, even when the standard library function is correct and could just have been used.
- Replacing standard library functions can hide bugs that would otherwise have found and fixed.
- Gnulib is not organized into the three categories and it's non-trivial to find out whether any interface has been replaced that shouldn't have been.
- There is no way to satisfy gnulib by correctly implementing the standard library without contributing explicit support upstream for new systems and committing to private implementation details.
Custom configure script
Configure scripts generated by autoconf are useful because they have a consistent interface. Ports with a hand-written configure script can fail if they fail to implement the autoconf configure interface correctly. The best solution is modify the configure script to implement the missing parts of the interface.Makefile
Ports might not have a configure script and only a makefile:BUILD_SYSTEM=makefile
Running cross-compiled program
Ports may contain logic errors and attempt to execute a cross-compiled program during the build, which fails because the program can't run on the current system.pkg-config
Ports are supposed to locate locate dependencies for the host machine using the PKG_CONFIG environment variable, and if unset, then using the --host option to locate a cross-pkg-config, and finally falling back on invoking pkg-config(1) directly . Dependencies for the build machine should likewise be located using the PKG_CONFIG_FOR_BUILD environment variable.${PKG_CONFIG:-pkg-config} ${PKG_CONFIG_FOR_BUILD:-${PKG_CONFIG:-pkg-config}}
foo-config instead of pkg-config
Ports are supposed to use pkg-config(1) as above for dependencies as it's a general solution with cross-compilation support, but some ports install their own foo-config program in the PATH. These programs are inherently unable to support cross-compilation, as they provide answers about the build machine, and the host machine's bin directory cannot be executed on the current machine.Bootstrap
Ports may require the same version of the port to be installed on the build machine when cross-compiling. Such ports can cross-compiled with a bootstrap phase:USE_BOOTSTRAP=true