Should we support BSD?

While I’m asking about Syft in this post, it’s a general question about a few tools.

Today I learned that June 19th is “FreeBSD Day”. It got me wondering what the state of our tools was on BSD.

(yes, I know macos is ‘technically’ kinda BSD under the covers, this is about ‘pure’ BSD (which may trigger some people, sorry (also not sorry))) (I think that’s enough close braces).

So, I tried building syft on FreeBSD 14.01

I grabbed go 1.21, and ran make bootstrap.

$ make bootstrap
make: "/home/alan/syft/Makefile" line 39: Unknown modifier "' | tr '\n' ' '" "
make: "/home/alan/syft/Makefile" line 39: Unknown modifier "' | cut -d '"
make: "/home/alan/syft/Makefile" line 39: Unknown modifier "' -f 3 | tr '\n' ' ' | tr -d ','""
make: "/home/alan/syft/Makefile" line 41: Unknown modifier "' | tr '\n' ' '" "
make: "/home/alan/syft/Makefile" line 41: Unknown modifier "' | cut -d '"
make: "/home/alan/syft/Makefile" line 41: Unknown modifier "' -f 3 | tr '\n' ' ' | tr -d ','""
make: "/home/alan/syft/Makefile" line 42: Unknown modifier "' | tr '\n' ' '" "
make: "/home/alan/syft/Makefile" line 42: Unknown modifier "' | cut -d '"
make: "/home/alan/syft/Makefile" line 42: Unknown modifier "' -f 3 | tr '\n' ' ' | tr -d ','""
make: Fatal errors encountered -- cannot continue
make: stopped in /home/alan/syft

Looks like this line is failing.

TASKS := $(shell bash -c "test -f $(TASK) && $(TASK) -l | grep '^\* ' | cut -d' ' -f2 | tr -d ':' | tr '\n' ' '" ) $(shell bash -c "test -f $(TASK) && $(TASK) -l | grep 'aliases:' | cut -d ':' -f 3 | tr '\n' ' ' | tr -d ','")

Which, after a small amount of digging, probably also means ./tool/task doesn’t exist, which is true. Also, ./tool/binny is missing.

So I dug a little deeper, and binny also isn’t available for BSD on amd64.

$ curl -sSfL https://raw.githubusercontent.com/anchore/binny/main/install.sh | sh -s -- -b /usr/local/bin
[info]\033[0m fetching release script for tag='v0.8.0' \033[0m
[info] using release tag='v0.8.0' version='0.8.0' os='freebsd' arch='amd64'
[error] could not find release asset for os='freebsd' arch='amd64' format='tar.gz'
[error] failed to install binny

So I thought, “I wonder if I can build binny from source for BSD for fun and frolics”

So I cloned GitHub - anchore/binny: Manage a directory of binaries without a package manager and tried:

alan@horns:~/binny $ make
make: "/home/alan/binny/Makefile" line 43: Unknown modifier "' | tr '\n' ' '" "
make: "/home/alan/binny/Makefile" line 43: Unknown modifier "' | cut -d '"
make: "/home/alan/binny/Makefile" line 43: Unknown modifier "' -f 3 | tr '\n' ' ' | tr -d ','""
make: "/home/alan/binny/Makefile" line 45: Unknown modifier "' | tr '\n' ' '" "
make: "/home/alan/binny/Makefile" line 45: Unknown modifier "' | cut -d '"
make: "/home/alan/binny/Makefile" line 45: Unknown modifier "' -f 3 | tr '\n' ' ' | tr -d ','""
make: "/home/alan/binny/Makefile" line 46: Unknown modifier "' | tr '\n' ' '" "
make: "/home/alan/binny/Makefile" line 46: Unknown modifier "' | cut -d '"
make: "/home/alan/binny/Makefile" line 46: Unknown modifier "' -f 3 | tr '\n' ' ' | tr -d ','""
make: Fatal errors encountered -- cannot continue
make: stopped in /home/alan/binny

And this feels recursive! :smiley:

So this feels like a few issues:

  1. There’s no binary build of syft for BSD
  2. There’s no binary build of binny for BSD
  3. binny doesn’t build for BSD on BSD
  4. make bootstrap doesn’t politely error (in binny and syft) when binny (and/or) task aren’t available

I could file issues in the appropriate repos. But I thought I’d ask the real question.

Should we support BSD?

Got an interesting reply from the tooterverse.

In short – heck yeah! I think getting binny, syft, and grype to run on BSD would be awesome. The makefile is there for folks like me that can’t seem to kick the muscle memory of make ..., but ultimately we’ve migrated over to task for development tasks, which is also releases on BSD (:partying_face: ). So worst case, say we don’t figure the best portable way for the make to work – we can side step it entirely.

1 Like

I had an idea: since the few tools we need happen to be go tools, and we require go to be installed to build anyway, could we use go to bootstrap the downloads needed? It should work in a cross-platform way.

I made a PR that probably needs a lot of work, but it seems to do this: chore: use go to bootstrap downloading and running task by kzantow · Pull Request #2959 · anchore/syft · GitHub

You could test it out like:

git clone git@github.com:kzantow-anchore/syft.git -b feat/go-build

Edit: it seems to definitely need some work, I got this error trying it out on a clean build:

[0021]  WARN failed to install all tools failed=[benchstat]
1 error occurred:
	* failed to install tool "benchstat": failed to install: installation failed: exit status 1
Output: go: downloading golang.org/x/perf v0.0.0-20240604174448-3b48cf0e0164
# internal/coverage/rtcov
compile: version "go1.22.4" does not match go tool version "go1.21.1"

Edit 2: everything passed in CI!

1 Like

For fun, building on the feedback from Mastodon, and what @kzantow suggested,I had a play, changing only a little of the Makefile and using GNU Make as gmake on BSD (sorry BSD people). I was trying to make as minimal a change as possible. :smiley:

diff --git a/Makefile b/Makefile
index 9089ee61..f26b34e8 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 OWNER = anchore
 PROJECT = syft
 
-TOOL_DIR = .tool
+TOOL_DIR = $(shell pwd)/.tool
 BINNY = $(TOOL_DIR)/binny
 TASK = $(TOOL_DIR)/task
 
@@ -12,12 +12,12 @@ TASK = $(TOOL_DIR)/task
 # note: we need to assume that binny and task have not already been installed
 $(BINNY):
        @mkdir -p $(TOOL_DIR)
-       @curl -sSfL https://raw.githubusercontent.com/$(OWNER)/binny/main/install.sh | sh -s -- -b $(TOOL_DIR)
+       @GOBIN=$(TOOL_DIR) go install -v github.com/anchore/binny@latest
 
 # note: we need to assume that binny and task have not already been installed
 .PHONY: task
 $(TASK) task: $(BINNY)
-       @$(BINNY) install task -q
+       @GOBIN=$(TOOL_DIR) go install -v github.com/go-task/task/v3/cmd/task@latest
 
 .PHONY: ci-bootstrap-go
 ci-bootstrap-go:

I thought rather than running the installer, I might just use go install and use GOBIN to coerce go install to put the built binary in the .tool folder. I think that works for task but not so much for binny

This is a binny main.go & go.mod location issue?

alan@horns:~/syft $ gmake
go: downloading github.com/anchore/binny v0.8.0
go: downloading github.com/OneOfOne/xxhash v1.2.8
go: downloading github.com/Masterminds/semver/v3 v3.2.1
go: downloading github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a
go: downloading github.com/go-git/go-git/v5 v5.11.0
go: downloading github.com/google/uuid v1.3.1
go: downloading github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e
go: downloading github.com/pjbgf/sha1cd v0.3.0
package github.com/anchore/binny is not a main package
gmake: *** [Makefile:15: /home/alan/syft/.tool/binny] Error 1

Sorry if I’m off base. Not a go expert, or a Makefile one, nor indeed a FreeBSD one. :smiley:

Is there a way to get run the same version of make in a container to figure out some of the differences between this and GNU make?

I guess that depends what platform you’re on.

On macOS, you can brew install bsdmake, and on Ubuntu there’s apt install bmake.

I went a bit overboard and installed an entire FreeBSD VM on my Linux laptop using quickemu which is a frontend to qemu. It’s really quite nice, as it also sets up an ssh tunnel from the host, and other nice stuff.

If you want to do that, it’s just a couple of commands once you’ve installed quickemu as per their instructions.

Get the FreeBSD installer, I chose 14.1, but other options are available:

$ quickget freebsd

FreeBSD
 - Credentials: -
 - Website:     https://www.freebsd.org/
 - Description: Operating system used to power modern servers, desktops, and embedded platforms.
 - Releases:    14.1 14.0 13.3 13.2 12.4
 - Editions:    disc1 dvd1

ERROR! You must specify a release.

Specify the release and

$ quickget freebsd 14.1 dvd1
Downloading FreeBSD 14.1 dvd1
- URL: https://download.freebsd.org/ftp/releases/amd64/amd64/ISO-IMAGES/14.1/FreeBSD-14.1-RELEASE-amd64-dvd1.iso
################################################################ 100.0%
Checking freebsd-14.1-dvd1/FreeBSD-14.1-RELEASE-amd64-dvd1.iso with sha256sum... Good!

To start your FreeBSD virtual machine run:
    quickemu --vm freebsd-14.1-dvd1.conf

Then do as it says to spin up the VM:

$ quickemu --vm freebsd-14.1-dvd1.conf

It will make a ‘hard disk’ image, boot from the ‘DVD’ and then just go through the installer like you normally would with any system. It’s nice and fast to install directly on your machine.

You’ll get output like this:

Quickemu 4.9.4 using /usr/bin/qemu-system-x86_64 v8.2.2
 - Host:     Ubuntu 24.04 LTS running Linux 6.9 (ziggy)
 - CPU:      AMD Ryzen 7 PRO 6860Z with Radeon Graphics
 - CPU VM:   1 Socket(s), 4 Core(s), 2 Thread(s), 8G RAM
 - BOOT:     EFI (Freebsd), OVMF (/usr/share/OVMF/OVMF_CODE_4M.fd), SecureBoot (off).
 - Disk:     freebsd-14.1-dvd1/disk.qcow2 (16G)
             Just created, booting from freebsd-14.1-dvd1/FreeBSD-14.1-RELEASE-amd64-dvd1.iso
 - Boot ISO: freebsd-14.1-dvd1/FreeBSD-14.1-RELEASE-amd64-dvd1.iso
 - Display:  SDL, qxl-vga, GL (on), VirGL (off)
 - Sound:    intel-hda
 - ssh:      On host:  ssh user@localhost -p 22221
 - WebDAV:   On guest: dav://localhost:9843/
 - 9P:       On guest:  - smbd:     On guest: smb://10.0.2.4/qemu
 - Network:  User (virtio-net)
 - Monitor:  On host:  nc -U "freebsd-14.1-dvd1/freebsd-14.1-dvd1-monitor.socket"
             or     :  socat -,echo=0,icanon=0 unix-connect:freebsd-14.1-dvd1/freebsd-14.1-dvd1-monitor.socket
 - Serial:   On host:  nc -U "freebsd-14.1-dvd1/freebsd-14.1-dvd1-serial.socket"
             or     :  socat -,echo=0,icanon=0 unix-connect:freebsd-14.1-dvd1/freebsd-14.1-dvd1-serial.socket
 - Process:  Starting freebsd-14.1-dvd1.conf as freebsd-14.1-dvd1 (1564927)

It’ll pop up a window to access the VM. But once installed you can ssh in as it shows above and carry on over that connection.

ssh alan@localhost -p 22221
(alan@localhost) Password for alan@horns:
Last login: Thu Jun 13 22:25:31 2024 from tmux(1663).%18
FreeBSD 14.1-RELEASE (GENERIC) releng/14.1-n267679-10e31f0946d8

Welcome to FreeBSD!

Release Notes, Errata: https://www.FreeBSD.org/releases/
Security Advisories:   https://www.FreeBSD.org/security/
FreeBSD Handbook:      https://www.FreeBSD.org/handbook/
FreeBSD FAQ:           https://www.FreeBSD.org/faq/
Questions List:        https://www.FreeBSD.org/lists/questions/
FreeBSD Forums:        https://forums.FreeBSD.org/

Documents installed with the system are in the /usr/local/share/doc/freebsd/
directory, or can be installed later with:  pkg install en-freebsd-doc
For other languages, replace "en" with a language code like de or fr.

Show the version of FreeBSD installed:  freebsd-version ; uname -a
Please include that output and any error messages when posting questions.
Introduction to manual pages:  man man
FreeBSD directory layout:      man hier

To change this login announcement, see motd(5).
To see all of the directories on your FreeBSD system, type

  find / -type d | less

All the files?

  find / -type f | less
alan@horns:~ $ cat /etc/os-release 
NAME=FreeBSD
VERSION="14.1-RELEASE"
VERSION_ID="14.1"
ID=freebsd
ANSI_COLOR="0;31"
PRETTY_NAME="FreeBSD 14.1-RELEASE"
CPE_NAME="cpe:/o:freebsd:freebsd:14.1"
HOME_URL="https://FreeBSD.org/"
BUG_REPORT_URL="https://bugs.FreeBSD.org/"
alan@horns:~ $ # BSD is FUN!

Great success.

Ok, I bit the bullet and got a FreeBSD VM installed (14.1). The branch referenced earlier works for me, now. It required a few tweaks to binny, so it’s using a branch of binny for the time being. The long-and-the-short of it is that most of the dependencies also don’t have a FreeBSD binary, so they also need to be go install’d. I updated the binny configuration for this. We probably don’t want this as a permanent solution, but rather something that tries to get a binary first and falls back to a go install, which I think will take a bit more enhancement of binny to achieve.

2 Likes

Can you help me understand why we don’t want to go install if it’s available?

@popey it looks like some of the errors you found were our use of shelling out to utilities like cut and tr from the Makefile. This shelling out also prevents us from easily running tests on Windows, so I think we should move away from it.

go install downloads all the dependencies and runs a build, which is pretty slow compared to just downloading a binary.