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 spkgbuild 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 spkgbuild 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/spkgbuild
    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

    spkgbuild format

    Each field in the spkgbuild 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 spkgbuild. 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 spkgbuild 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="-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 spkgbuild

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

    $ vim spkgbuild

    The complete spkgbuild 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 spkgbuild 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
    ==> .checksums 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
    ...
    ==> .pkgfiles 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.