Skip to content

CI: build and test on FreeBSD and OpenBSD - #1384

Open
neilpang wants to merge 1 commit into
martanne:masterfrom
neilpang:bsd-ci
Open

CI: build and test on FreeBSD and OpenBSD#1384
neilpang wants to merge 1 commit into
martanne:masterfrom
neilpang:bsd-ci

Conversation

@neilpang

Copy link
Copy Markdown

The sourcehut builds stopped running on 2026-02-06. builds.sr.ht shows
no job after #1674603, and 119 commits have landed since; the badge in
README still reads success from that last run.

https://builds.sr.ht/~martanne/vis

This adds a FreeBSD job and an OpenBSD job that run in VMs on
GitHub-hosted runners, so a BSD result appears on every push and pull
request here, next to Ubuntu and macOS.

gmake, not make

Both jobs call gmake rather than make, and .builds/freebsd.yml and
.builds/openbsd.yml would fail today because they call make.

The Makefile computes two values with $(shell ...), which is a GNU make
extension:

VERSION = $(shell git describe --always --dirty 2>/dev/null || echo "v0.9-git")
API     = $(shell git rev-list --count HEAD 2>/dev/null || echo "0")

BSD make does not implement it, so under make both expand to nothing --
the fallbacks never get a chance to run either. -DVERSION="" is a
harmless empty string, but -DVIS_API= is an empty macro that still
counts as defined, so the

#ifndef VIS_API
  #define VIS_API 0
#endif

fallback in util.h does not fire, and vis-lua.c:3391 becomes
lua_pushinteger(L, ):

./vis-lua.c:3391:28: error: expected expression
 3391 |         lua_pushinteger(L, VIS_API);
      |                                   ^

$(shell ...) has been in the Makefile since 2015, but it only started
breaking the build on 2026-06-26, when 0515140 added vis.API and gave
VIS_API a use site where an empty expansion is not valid C. That is
four months after the sourcehut builds stopped, which is why it went
unnoticed.

Under gmake the fallbacks work: the VM has no .git, so both shell
commands fail and VERSION becomes "v0.9-git" and VIS_API becomes 0.

What the jobs cover

The same configure variants the ubuntu and macOS jobs use:

FreeBSD 15.1   ""  --disable-curses  --disable-lua
               --disable-tre  --disable-help
OpenBSD 7.9    ""  --disable-curses  --disable-lua  --disable-help

OpenBSD has no --disable-tre entry because 7.9 packages no libtre, so
configure already reports "checking for libtre... no" there and the
default build has no tre to disable.

Results, from
https://github.com/neilpang/vis/actions/runs/31863428494 and
https://github.com/neilpang/vis/actions/runs/31863428537 :

FreeBSD  5/5 green, 1.9 to 2.1 min per config
OpenBSD  4/4 green, 2.9 to 3.3 min per config

every config: Tests ok 8/8, Tests ok 65/65,
              Tests ok 6/6 skipped 28, no failures

--disable-lua drops the two lua suites, as it should, and the
binary reports +curses +tre with no +lua

One thing this does not fix

7d53cd6 added five calls to towlower, towupper and iswlower in main.c
without including <wctype.h>; nothing in the tree includes it. Both
BSDs warn five times:

main.c:393:11: warning: call to undeclared function 'towlower';
ISO C99 and later do not support implicit function declarations
[-Wimplicit-function-declaration]

These are warnings and not what breaks the build, so the jobs are green
with them present. They are invalid C99 though, and would become errors
under a compiler that defaults to rejecting implicit declarations. I
left it alone since it is a separate change from adding CI; happy to
send it as its own PR if you want it.

Left alone deliberately

  • .builds/freebsd.yml and .builds/openbsd.yml, README's sourcehut
    badge: what you want to do with sourcehut is your call.
  • No coverage upload. The ubuntu and macOS jobs build with
    --coverage and push to codecov; the sourcehut builds never did, and
    the .gcda files would have to be copied back out of the VM first.
    Easy to add if you want it.
  • actions/checkout is @v7 in the new files while the existing ones
    are on @v6. I did not touch them, to keep this to one change.

The sourcehut builds stopped running on 2026-02-06; 119 commits have
landed since.  builds.sr.ht shows no job after #1674603, and the badge
in README still reads success from that last run.

These two jobs run the same builds in VMs on GitHub-hosted runners, so
the result shows up on every push and pull request here.

They call gmake rather than make.  The Makefile computes VERSION and
API with $(shell ...), which is a GNU make extension; under BSD make
both expand to nothing, and the resulting empty -DVIS_API= defeats the
"#ifndef VIS_API" fallback in util.h, so vis-lua.c:3391 fails with
"error: expected expression".  That has been true since 0515140
(2026-06-26) added vis.API, four months after the sourcehut builds
stopped, which is why nobody saw it.  .builds/freebsd.yml and
.builds/openbsd.yml still say make for the build step and would fail
today for the same reason.

Verified in FreeBSD 15.1 and OpenBSD 7.9 VMs, every configure variant
the ubuntu and macOS jobs use:

    FreeBSD   "" --disable-curses --disable-lua --disable-tre
              --disable-help        all build, tests 8/8 65/65 6/6
    OpenBSD   "" --disable-curses --disable-lua --disable-help
              all build, tests 8/8 65/65 6/6

OpenBSD gets no --disable-tre entry because 7.9 has no libtre package,
so tre is already absent from the default build there.
@rnpnr

rnpnr commented Aug 16, 2026

Copy link
Copy Markdown
Collaborator

Thanks for this! I will have to test in my personal fork.

The sourcehut builds stopped running on 2026-02-06. builds.sr.ht shows
no job after #1674603, and 119 commits have landed since; the badge in
README still reads success from that last run.

Yes at some point source hut stopped letting unpaid members start jobs (or martanne stopped being a paid member). I didn't look into it very far because I'm not particularly keen on sourcehut.

but -DVIS_API= is an empty macro that still counts as defined, so the

#ifndef VIS_API
  #define VIS_API 0
#endif

fallback in util.h does not fire

Those fallbacks were meant for the much simpler case of building which is what I do and what should probably be the default at some point:

#!/bin/sh

CFLAGS="-O0 -gdwarf-4"
#CFLAGS="-O3"
#CFLAGS="${CFLAGS} -fsanitize=address,undefined -fsanitize-trap=all"
#CFLAGS="${CFLAGS} -fproc-stat-report"

#CFLAGS="${CFLAGS} -DCONFIG_CURSES=1"
#LDFLAGS="-ltinfow -lncursesw"

clang -march=native ${CFLAGS} -Wall -std=c99 -pedantic \
      -Wno-initializer-overrides \
      -DVIS_EXPORT=static \
      -DVIS_PATH=\"/usr/alt/share/vis\"\
      -DVERSION=\"$(git describe --always --dirty 2>/dev/null || echo "v0.9-git")\" \
      -DVIS_API=$(git rev-list --count HEAD 2>/dev/null || echo "0") \
      -DCONFIG_LUA=1 \
      -I/usr/include/lua5.4 \
      main.c -o vis -llua5.4 ${LDFLAGS}

with the assumption being that -DVIS_API is not passed. I can't be bothered to write some shell script that handles all the random things in the Makefile and without removing the Makefile people will think that's how the project should be built. So here we are.

7d53cd6 added five calls to towlower, towupper and iswlower in main.c
without including <wctype.h>;

Fixed, glibc is a horrific mess so even if you include the most basic header like stdint.h it pulls in pretty much every other header in libc so these things get missed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants