root@starkos:~$ portcreate

Create ports

How the starkOS ports system works and how to create your own with portcreate, from the initial template to the installable package.

A port is the recipe, or set of instructions, that describes how to build a program from its source code: where to download it from, what dependencies it needs, and what commands must be run to compile and install it. In starkOS a port is, in practice, a directory containing an sbuild template, which is the minimum that starkpm requires to build a package. In some ports you may additionally find patches, configuration files, or pre/post-install and pre/post-remove hooks that need to run during the installation or removal of the port on the system.

It's easy to confuse the two terms because one becomes the other, but they serve different purposes:

In short: you build a port to obtain an installable package on the system; the portsync command syncs ports (recipes), not packages — each machine compiles its own packages from ports.

  1. 01

    Requirements and local repository

    You need fakeroot to build ports without using root directly. Install it with starkpm if you don't already have it:

    # portsync
    # stark install fakeroot

    It's recommended to keep your own ports in a local repository, inside your home directory:

    $ mkdir $HOME/local
  2. 02

    Create the template with portcreate

    As an example, dfc will be used, a command-line tool that displays disk space usage with graphs and colors. Use portcreate <portname> to generate the initial template and enter its directory:

    $ portcreate 
    Usage: portcreate [-b builder] 
    
    Create a port template directory with sbuild file.
    
    Options:
      -b   Specify build system (default: autotools)
                    Available: autotools, meson, cmake, go, python
      -h            Show this help message
    
    Examples:
      portcreate myport              # Creates autotools template
      portcreate -b meson myport     # Creates meson template
      portcreate -b cmake myport     # Creates cmake template
      portcreate -b go myport        # Creates go template
      portcreate -b python myport    # Creates python template

    The generated template looks like this:

    $ portcreate myport
    	    Template port created for 'myport' using 'autotools' build system.
    	    
    $ cat myport/sbuild
    description="" maintainer="starkOS Team, starkos at disroot dot org" homepage="" name=myport version= release=1 noextract="" backup="" source="" build() { cd $name-$version ./configure --prefix=/usr make make DESTDIR="$PKG" install }
  3. 03

    sbuild format

    Each field in the sbuild serves a specific purpose:

    Field Required Description
    descriptionYesBrief description of the port
    maintainerYesPort maintainer
    homepageYesProject website
    dependsNoDependencies, in a separate file within the port directory
    nameYesPort name, same as the directory
    versionYesProgram version
    releaseYesPort revision for the same version
    sourceYesRemote location of the source code
    noextractNoSources that should not be extracted
    backupNoFiles to preserve during an update
    nostripNoFiles to exclude from stripping
    build()YesFunction containing the build commands

    Inside build(), $PKG is the simulated install directory and $SRC is the directory where the extracted sources end up.

    The port name must be lowercase and cannot contain spaces; if the original project uses uppercase, fix it with sed when writing the sbuild. If the source uses date-based versioning, hyphens (-) cannot be used — replace them with underscores (_) or dots (.) if strictly necessary.

  4. 04

    Recommended schemes for each builder

    Global options are defined in /etc/starkpm.conf; for a specific port they are overridden in its own sbuild with options="". Prefix with ! to disable an option, for example options="!strip !emptydirs".

    make
    
    ./configure \
        	--prefix=/usr \
        	--disable-option \
        	--enable-option
    make
    make DESTDIR="$PKG" install
    
    autoconf / automake
    
    autoreconf -fi
    ./configure \
        	--prefix=/usr \
        	--disable-option \
        	--enable-option
    make
    make DESTDIR="$PKG" install
    
    meson
    

    The distribution provides a starkos-meson wrapper script which sets some common options.

    starkos-meson $name-$version build \ -Doption=false \ -Doption2=true meson compile -C build DESTDIR="$PKG" meson install --no-rebuild -C build
    cmake
    
    cmake -S $name-$version -B build \
    	-DCMAKE_INSTALL_PREFIX=/usr \
    	-DCMAKE_INSTALL_LIBDIR=lib \
    	-DCMAKE_INSTALL_LIBEXECDIR=lib \
    	-DCMAKE_BUILD_TYPE=Release \
    	-DCMAKE_C_FLAGS_RELEASE="$CFLAGS" \
    	-DCMAKE_CXX_FLAGS_RELEASE="$CXXFLAGS" \
    	-DOPTION=ON/OFF \
    	-Wno-dev
    cmake --build build
    DESTDIR="$PKG" cmake --install build
    
    go
    
    cd $name-$version
    
    	export CGO_LDFLAGS="${LDFLAGS}"
    	export CGO_CFLAGS="${CFLAGS}"
    	export CGO_CPPFLAGS="${CPPFLAGS}"
    	export CGO_CXXFLAGS="${CXXFLAGS}"
    	export GOFLAGS="$GOFLAGS -buildmode=pie -trimpath -mod=readonly \
    			-modcacherw -ldflags=-linkmode=external"
    	export GOPATH="$SRC"/go
    	export PATH="$PATH":"$GOPATH"/bin
    
    go build -o bin/$name *.go
    
    python
    
    python3 setup.py build
    python3 setup.py install --prefix=/usr --root="$PKG"
    
    
    pip (python) 
    
    pip3 install --isolate --root="$PKG"
    
    
    build (python)
    
    python3 -m build --wheel --skip-dependency-check --no-isolation
    python3 -m installer --destdir="$PKG"
    
    gpep517 (python)
    
    gpep517 build-wheel --wheel-dir .dist --output-fd 3 3>&1 >&2
    python3 -m installer -d "$PKG"  .dist/*.whl
    
  5. 05

    Edit the sbuild

    With the format clear, you can now fill in the template with curl's actual data:

    $ vim sbuild

    The complete sbuild for dfc would look like this:

    description="Utility and a library used for transferring files"
    homepage="https://curl.se"
    maintainer="starkOS Team, starkos at disroot dot org"
    
    name=curl
    version=8.21.0
    release=1
    source="https://curl.haxx.se/download/$name-$version.tar.xz"
    
    build() {
    	cd $name-$version
    
    	autoreconf
    	./configure \
    		--prefix=/usr \
    		--disable-static \
    		--disable-ldap \
    		--disable-ldaps \
    		--enable-ipv6 \
    		--enable-threaded-resolver \
    		--with-ca-bundle=/etc/ssl/cert.pem \
    		--with-ca-path=/etc/ssl/certs \
    		--with-nghttp2 \
    		--with-openssl \
    		--without-brotli \
    		--without-libidn2 \
    		--without-libpsl \
    		--without-librtmp \
    		--without-zstd 
    	make
    	make DESTDIR="$PKG" install
    }
    

    It's recommended to save sources following "$name-$version.*". If the source needs to be saved under a different name, use <new-name>::<url> in source="", for example "$name-$version.tar.gz::https://project/file/v${version}.tar.gz".

  6. 06

    Build the package

    With the sbuild finished, run portbuild inside the port's directory to download the source and compile it. For a new port, do this first with fakeroot; if something is misconfigured, it won't affect your system.

    $ fakeroot portbuild
    ==> Building: curl-8.21.0-1
    ==> Fetching: https://curl.haxx.se/download/curl-8.21.0.tar.xz
    ==> .csums updated
    ==> Unpacking: /mnt/starkos/var/cache/starkpm/sources/curl-8.21.0.tar.xz
    
    ==> Build start: curl-8.21.0-1
    + build
    + cd curl-8.21.0
    + autoreconf
    ...
    ==> .files updated
    ==> Packaging success: curl-8.21.0-1.spkg.tar.xz (1.3M)
    	    
  7. 07

    Install the package

    Once built, you can install it directly with portbuild:

    # portbuild -i

For dependencies, repository synchronization, and updating the system once the package is installed, see the install guide.