Evilham

Evilham.com

FreeBSD adopting a port: maomao

Introduction

The Fediverse is a wonderful place, and the #FreeBSD community over there is rather active :-).

Justine Smithies is one those people with whom we have had multiple constructive interactions, and she has made lovely contributions to FreeBSD’s community, starting with her enthusiasm!

Recently, she’s been toying around with maomao, a Wayland compositor.

And I promised to create a port if she committed to keeping it up to date (neat trick to get new contributors!)

Let’s document both that process, and how she can keep those patches coming in to the ports tree!

Table of Contents

FreeBSD and the ports tree

You may want to read my (now outdated) post on updating a FreeBD port, which goes into detail about the Source trees, but most technical bits are outdated by now, given that FreeBSD has moved away from svn and now uses git to manage code.

The short version about FreeBSD‘s Source trees (plural!). Without going into much detail: FreeBSD has a base (or src) tree and a ports tree.

The base tree contains the whole Operating System along with any necessary system utilities and they are developed as a unit.

While the ports tree contains a description of how to compile third-party software under FreeBSD and how to install it manually or how to build an installable binary package, which can later on be built on FreeBSD‘s infrastructure and served by official pkg repositories.

Wayland on FreeBSD?

Contrary to popular belief, Wayland is not something that is exclusive to Linux. While it is Linux-centric, it does support FreeBSD, even as a test target on its CI!

Some things that are worth checking on this topic (though some might be outdated, they are still worth it):

There are in fact right now 140 ports with ‘Wayland’ on their description (source: quick pkg(8) magic).

Maomao

As usual with Wayland things, it is written with Linux in mind, but as it often happens, that does not mean the authors are hostile towards supporting FreeBSD, they just might not be aware that the OS can be a target.

In fact, the author recently committed some code that helps mmsg (a companion tool to maomao) bulid on FreeBSD without patches.

So if we run into issues, we can be reasonably sure that a patch will be welcome.

Getting started with ports

I have previously created several ports and update some from time to time, so I was able to take shortcuts and creating the ports was relatively quick.

Setting up poudriere(8)

With poudriere(8), we’ll be able to manage building the ports with jails and producing a local repository of packages, that we can easily install, as well as manage the ports tree.

Once poudriere(8) is installed with pkg install poudriere, we can check its configuration under /usr/local/etc/poudriere.conf.

Here is what I like to adapt from the sample file:

# Use the ZFS dataset zroot/poudriere
ZPOOL=zroot
ZROOTFS=/poudriere
# Which is mounted on /poudriere
BASEFS=/poudriere
# Suggested value
FREEBSD_HOST=https://download.FreeBSD.org
# DNS resolution for jails
RESOLV_CONF=/etc/resolv.conf
# Use tempfs(5) for wrdir and data
USE_TMPFS=yes
# Adapt this to your CPU count, leaving some for your regular use
PARALLEL_JOBS=6
# I have found timestamps to be useful
TIMESTAMP_LOGS=yes
# I like to keep old versions around
KEEP_OLD_PACKAGES=yes
KEEP_OLD_PACKAGES_COUNT=2
# Use the 'latest' ports branch when fetching pre-buit binaries
PACKAGE_FETCH_BRANCH="latest"

Getting the ports tree

This can be done in multiple ways, the most convenient one is getting the code from the same repository that is used by developers over anonymous git with poudriere(8):

# Fetch the ports tree
> poudriere ports -c -p default

Creating the port

Luckily, this is a fairly standard port, we start by identifying a somewhat similar port, like x11-wm/swayfx, and using it as a starting point.

Here is roughly what that looks like:

PORTNAME=   maomao
DISTVERSION=    g20250624

CATEGORIES= x11-wm

MAINTAINER= ports@FreeBSD.org
COMMENT=    A streamlined but feature-rich Wayland compositor
WWW=        https://github.com/DreamMaoMao/maomaowm

LICENSE=    MIT
LICENSE_FILE=   ${WRKSRC}/LICENSE

USES=       meson pkgconfig desktop-file-utils

OPTIONS_DEFINE= X11
OPTIONS_DEFAULT=X11

X11_MESON_ENABLED=  xwayland

USE_GITHUB= yes
GH_ACCOUNT= DreamMaoMao
GH_PROJECT= maomaowm
GH_TAGNAME= e8fe574

.include <bsd.port.mk>

We then check the meson.build file, which lists all its dependencies.

And adapt entries acordingly:

BUILD_DEPENDS=  wayland-scanner:graphics/wayland \
        wayland-protocols>0:graphics/wayland-protocols \
        evdev-proto>0:devel/evdev-proto
LIB_DEPENDS=    libscenefx-0.4.so:x11-toolkits/scenefx04 \
        libwlroots-0.19.so:x11-toolkits/wlroots019

X11_LIB_DEPENDS=    libxcb-icccm.so:x11/xcb-util-wm
X11_USE=        XORG=xcb,pixman

I also identify that we need the same sample file, version and C flag patches that x11-wm/swayfx implements, so I copy and adapt those:

post-patch:
# Extract (snapshot) version from the port instead of meson.build
    @${REINPLACE_CMD} -i .nogit -e 's/git.found()/false/' \
        -e '/unknown/s/@0@/${DISTVERSIONFULL}/' \
        ${WRKSRC}/meson.build
# Fix C flags
# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=275328
    @${REINPLACE_CMD} -e 's/_POSIX_C_SOURCE=200809L/_XOPEN_SOURCE=700/' \
        ${WRKSRC}/meson.build
# Respect PREFIX for system-wide config
    @${REINPLACE_CMD} -e "s,format('/etc'),format('${PREFIX}/etc')," \
        ${WRKSRC}/meson.build

post-install:
# Install config file as a sample
    @${MV} ${STAGEDIR}${ETCDIR}/config.conf \
        ${STAGEDIR}${ETCDIR}/config.conf.sample

We update / generate the distinfo file with make makesum.

Then the pkg-plist file:

bin/maomao
@sample %%ETCDIR%%/config.conf.sample
share/wayland-sessions/maomao.desktop

And also create the pkg-descr file:

A streamlined but feature-rich Wayland compositor

1. **Lightweight & Fast Build**
   - *Maomao* is as lightweight as *dwl*, and its build can be completed within
     few seconds. Despite this, *maomao* does not compromise on functionality.

2. **Feature Highlights**
   - In addition to basic WM functionality, Maomao provides:
     - Base tag not workspace (supports separate window layouts for each tag)
     - Smooth and customizable complete animations (window open/move/close, tag
       enter/leave)
     - Excellent input method support (text input v2/v3)
     - Flexible window layouts with easy switching (scroller, master, monocle,
       spiral, etc.)
     - Rich window states (swallow, minimize, maximize, unglobal, global,
       fakefullscreen, overlay, etc.)
     - Simple yet powerful external configuration
     - Sway-like scratchpad and named scratchpad
     - Minimize window to scratchpad
     - Hycov-like overview
     - Window effects from scenefx(blur, shadow, corner radius, opacity)

And the pkg-message file, which gets shown upon install:

[
{ type: install
  message: <<EOM
The default configuration works best by installing foot(1) and rofi(1)
alongside maomao.

Also, keep these default shortcuts in mind:
- alt+return: open foot terminal
- alt+q: kill client
- alt+left/right/up/down: focus direction
- super+m: quit maomao
EOM
}
]

Building the port

We do this with poudriere(8), which uses jails and ZFS snapshots.

We first have to create the jail, if we haven’t already:

# Create a builder jail for amd64 based on 14.3-RELEASE
> poudriere jail -c -j 143-amd64 -v 14.3-RELEASE
# We also can keep the jail up to date with:
# poudriere jail -u -j 143-amd64

And we can now instruct poudriere(8) to use our ports tree with this jail to build this port:

# Start jail 143-amd64, with the default ports tree, to build maomao
> poudriere bulk -j 143-amd64 -p default x11-wm/maomao

This will fetch all needed packages along with their dependencies, so we only have to build locally the port we need.

Testing the port

Once the port builds (which required a small code patch), we can install it with:

# Install the resulting maomao binary pkg
> pkg add /poudriere/data/packages/143Ramd64-default/All/maomao-g20250624.pkg

And we can then run it as usual.

Updating the port

The recurring work of updating the port lies in updating the Makefile with each release. Usually dependencies are pretty stable, other than that we just have to:

  • change the PORTVERSION to match the latest release
    • In the case of mmsg, that’d be DISTVERSION and GH_TAGNAME, this is because it does not currently have actual releases
  • update the checksums with make makesum
  • test that the port builds and works
  • submit a patch to bugs.FreeBSD.org

Submitting the patch

Now that we created two ports: x11-wm/maomao and deskutils/mmsg, we can submit them and hope that they get merged soon.

Since Diane Bruce offered to help commit this, we add her as a reviewer. And since further maintainership is going to Justine, we add her on CC.

You can check the patch and its state [here][pr_maomao].

[pr_maomao]:

Conclusions

Generally speaking, I would advise people who want to get into contributing to the ports tree, to start by updating ports that they use and care about.

Committers and maintainers are usually happy to have a patch to quickly review and test as opposed to having to do the whole work.

In this case, since the port did not exist, it might be easier to nerdsnipe someone into creating the ports, and then helping out with the maintenance ;-) which is always super needed and appreciated!