Post

pkgsrc (6/6)

This post is an automatic translation from French. You can read the original version here.

Today, we’re going to make Go application packages with pkgsrc. It’s a somewhat “tired” Imil who shows us how to go about it … well … if he manages to survive the intro! ^^’

As always, the video is available here and I strongly recommend watching it.

Go in pkgsrc

To talk about Go in pkgsrc, let’s start by talking about someone: benz. He’s the one we owe Go support in pkgsrc to!

To get a quick look at how it works, just take a peek at the pkgsrc directory tree:

$ cd /usr/pkgsrc

$ ls lang/go
CVS             Makefile        go-dep.mk       go-package.mk   version.mk
DESCR           bootstrap.mk    go-module.mk    go-vars.mk

As you can see, it contains mk files that make it easy to create Go packages.

And notably, the go-module.mk file to include in our package’s Makefile!!

For details, you can check out Benny’s blog here.

Thanks to Benny, even if there’s no module support in the software to be packaged, that’s fine: we can do it ourselves. Great, isn’t it? Indeed, by default, when you compile a Go tool, the result is a static binary. So there’s not much point in being modular! Generally, in a Go project, you’ll fetch the modules you need to compile, then it compiles statically into one big binary. All of this is done very simply with pkgsrc!

Let’s go! Let’s package something!

The program we’re going to package today is called go-md2man: it converts markdown into manpages. A good habit, before getting started, is to always check whether the package already exists!

$ pkgin se md2man
go-md2man-2.0.1nb7   Converts markdown into roff (man pages)

=: package is installed and up-to-date
<: package is installed but newer version is available
>: installed package has a greater version than available package

AH. The package already exists!

Normally, this would mean we should not repackage it. It would be healthier, if this package doesn’t suit our needs, to offer contributions to its author.

However, here, we’re learning. So we’ll do it anyway, then compare our approach to that of the package’s author!

We start, as always, by using url2pkg:

$ cd /usr/pkgsrc/wip

$ mkdir go-md2man

$ cd go-md2man

$ url2pkg https://github.com/cpuguy83/go-md2man/archive/refs/tags/v2.0.2.zip
===> Cleaning for go-md2man-2.0.2
=> Bootstrap dependency digest>=20211023: found digest-20220214
WARNING: [license.mk] Every package should define a LICENSE.
=> Fetching go-md2man-2.0.2.zip
Requesting https://github.com/cpuguy83/go-md2man/archive/refs/tags/v2.0.2.zip
Redirected to https://codeload.github.com/cpuguy83/go-md2man/zip/refs/tags/v2.0.2
Requesting https://codeload.github.com/cpuguy83/go-md2man/zip/refs/tags/v2.0.2
 73323        1.32 MiB/s
73323 bytes retrieved in 00:00 (1.31 MiB/s)
=> Checksum BLAKE2s OK for go-md2man-2.0.2.zip
=> Checksum SHA512 OK for go-md2man-2.0.2.zip
===> Installing dependencies for go-md2man-2.0.2
=> Tool dependency cwrappers>=20150314: found cwrappers-20220403
=> Tool dependency checkperms>=1.1: found checkperms-1.12
===> Skipping vulnerability checks.
WARNING: No /var/db/pkg/pkg-vulnerabilities file found.
WARNING: To fix run: `/usr/pkg/sbin/pkg_admin -K /var/db/pkg fetch-pkg-vulnerabilities'.
===> Overriding tools for go-md2man-2.0.2
===> Extracting for go-md2man-2.0.2

Remember to run pkglint when you're done.
See ../../doc/pkgsrc.txt to get some help.

Here is the Makefile we get:

# $NetBSD$

GITHUB_TAG=     refs/tags/v${PKGVERSION_NOREV}
DISTNAME=       go-md2man-2.0.2
CATEGORIES=     # TODO: add primary category
MASTER_SITES=   ${MASTER_SITE_GITHUB:=cpuguy83/}
EXTRACT_SUFX=   .zip

MAINTAINER=     INSERT_YOUR_MAIL_ADDRESS_HERE # or use pkgsrc-users@NetBSD.org
HOMEPAGE=       https://github.com/cpuguy83/go-md2man/
COMMENT=        TODO: Short description of the package
#LICENSE=       # TODO: (see mk/license.mk)

USE_LANGUAGES=  # none

.include "../../mk/bsd.pkg.mk"

Based on this Makefile, we make a few changes:

# $NetBSD$

GITHUB_TAG=     v${PKGVERSION_NOREV}
DISTNAME=       go-md2man-2.0.2
CATEGORIES=     textproc
MASTER_SITES=   ${MASTER_SITE_GITHUB:=cpuguy83/}
EXTRACT_SUFX=   .zip

MAINTAINER=     rancune@rancune.org
HOMEPAGE=       https://github.com/cpuguy83/go-md2man/
COMMENT=        Converts markdown into roff ( Man pages )
LICENSE=        mit

USE_LANGUAGES=  # none

.include "../../lang/go/go-module.mk"
.include "../../mk/bsd.pkg.mk"

As you can see, this is fairly similar to what we did in previous installments. However, there’s a small novelty on the second-to-last line: we included the “go-module.mk” file mentioned earlier.

We can now fetch the sources and update distinfo:

$ make fetch
=> Bootstrap dependency digest>=20211023: found digest-20220214
=> Fetching go-md2man-2.0.2.zip
=> Total size: 73323 bytes
Requesting https://github.com/cpuguy83/go-md2man/archive/v2.0.2.zip
Redirected to https://codeload.github.com/cpuguy83/go-md2man/zip/refs/tags/v2.0.2
Requesting https://codeload.github.com/cpuguy83/go-md2man/zip/refs/tags/v2.0.2
 73323      569.22 KiB/s
73323 bytes retrieved in 00:00 (568.08 KiB/s)

$ make distinfo
=> Bootstrap dependency digest>=20211023: found digest-20220214

For managing the Go modules used by md2man, pkgsrc will take care of everything. You just need to create the list of required modules:

$ make show-go-modules
# get https://proxy.golang.org/github.com/russross/blackfriday/v2/@v/v2.1.0.mod
# get https://proxy.golang.org/github.com/russross/blackfriday/v2/@v/v2.1.0.mod: 200 OK (0.064s)
# get https://proxy.golang.org/github.com/russross/blackfriday/v2/@v/v2.1.0.info
# get https://proxy.golang.org/github.com/russross/blackfriday/v2/@v/v2.1.0.info: 200 OK (0.003s)
# get https://proxy.golang.org/github.com/russross/blackfriday/v2/@v/v2.1.0.zip
# get https://proxy.golang.org/github.com/russross/blackfriday/v2/@v/v2.1.0.zip: 200 OK (0.005s)
# $NetBSD$

GO_MODULE_FILES+=       github.com/russross/blackfriday/v2/@v/v2.1.0.mod
GO_MODULE_FILES+=       github.com/russross/blackfriday/v2/@v/v2.1.0.zip

$ make show-go-modules > go-modules.mk

Now that the go-modules.mk file is generated, all that’s left is to include it in our Makefile:

# $NetBSD$

GITHUB_TAG=     v${PKGVERSION_NOREV}
DISTNAME=       go-md2man-2.0.2
CATEGORIES=     textproc
MASTER_SITES=   ${MASTER_SITE_GITHUB:=cpuguy83/}
EXTRACT_SUFX=   .zip

MAINTAINER=     rancune@rancune.org
HOMEPAGE=       https://github.com/cpuguy83/go-md2man/
COMMENT=        Converts markdown into roff ( Man pages )
LICENSE=        mit

USE_LANGUAGES=  # none

.include "go-modules.mk"
.include "../../lang/go/go-module.mk"
.include "../../mk/bsd.pkg.mk"

The rest of the process should now be starting to feel familiar. We update the DESCR file, then use the usual commands:

$ make distinfo
=> Bootstrap dependency digest>=20211023: found digest-20220214
=> Fetching github.com_russross_blackfriday_v2_@v_v2.1.0.mod
[...]
122358 bytes retrieved in 00:00 (8.38 MiB/s)

$ make
=> Bootstrap dependency digest>=20211023: found digest-20220214
===> Skipping vulnerability checks.
WARNING: No /var/db/pkg/pkg-vulnerabilities file found.
WARNING: To fix run: `/usr/pkg/sbin/pkg_admin -K /var/db/pkg fetch-pkg-vulnerabilities'.
===> Creating toolchain wrappers for go-md2man-2.0.2
===> Configuring for go-md2man-2.0.2
=> Checking for portability problems in extracted files
===> Building for go-md2man-2.0.2
github.com/russross/blackfriday/v2
github.com/cpuguy83/go-md2man/v2/md2man
github.com/cpuguy83/go-md2man/v2

$ make print-PLIST >  PLIST

$ make stage-install
=> Bootstrap dependency digest>=20211023: found digest-20220214
===> Skipping vulnerability checks.
WARNING: No /var/db/pkg/pkg-vulnerabilities file found.
WARNING: To fix run: `/usr/pkg/sbin/pkg_admin -K /var/db/pkg fetch-pkg-vulnerabilities'.
===> Installing for go-md2man-2.0.2
=> Generating pre-install file lists
=> Creating installation directories
=> Automatic manual page handling
=> Generating post-install file lists
=> Checking file-check results for go-md2man-2.0.2
=> Checking for non-existent script interpreters in go-md2man-2.0.2
=> Checking file permissions in go-md2man-2.0.2
=> Checking for missing run-time search paths in go-md2man-2.0.2
=> Checking for work-directory references in go-md2man-2.0.2

$ make clean
===> Cleaning for go-md2man-2.0.2

$ pkglint
Looks fine.

$ sudo make install
[...]
===> Installing for go-md2man-2.0.2
=> Generating pre-install file lists
=> Creating installation directories
=> Automatic manual page handling
=> Generating post-install file lists
=> Checking file-check results for go-md2man-2.0.2
=> Checking for non-existent script interpreters in go-md2man-2.0.2
=> Checking file permissions in go-md2man-2.0.2
=> Checking for missing run-time search paths in go-md2man-2.0.2
=> Checking for work-directory references in go-md2man-2.0.2
=> Creating binary package /usr/pkgsrc/wip/go-md2man/work/.packages/go-md2man-2.0.2.tgz
===> Building binary package for go-md2man-2.0.2
=> Creating binary package /usr/pkgsrc/packages/All/go-md2man-2.0.2.tgz
===> Installing binary package of go-md2man-2.0.2

$ go-md2man --help
Usage of go-md2man:
  -in string
        Path to file to be processed (default: stdin)
  -out string
        Path to output processed file (default: stdout)

And it’s a victory \o/

Shall we compare?

Since md2man was already packaged in the pkgsrc tree, we can compare our work with that of an experienced packager.

Here is our Makefile:

# $NetBSD$

GITHUB_TAG=     v${PKGVERSION_NOREV}
DISTNAME=       go-md2man-2.0.2
CATEGORIES=     textproc
MASTER_SITES=   ${MASTER_SITE_GITHUB:=cpuguy83/}
EXTRACT_SUFX=   .zip

MAINTAINER=     rancune@rancune.org
HOMEPAGE=       https://github.com/cpuguy83/go-md2man/
COMMENT=        Converts markdown into roff ( Man pages )
LICENSE=        mit

USE_LANGUAGES=  # none

.include "go-modules.mk"
.include "../../lang/go/go-module.mk"
.include "../../mk/bsd.pkg.mk"

And here is the one from the package located in /usr/pkgsrc/textproc/go-md2man:

# $NetBSD: Makefile,v 1.46 2022/04/13 07:50:54 bsiegert Exp $

DISTNAME=       go-md2man-2.0.1
MASTER_SITES=   ${MASTER_SITE_GITHUB:=cpuguy83/}
PKGREVISION=    8
CATEGORIES=     textproc
GITHUB_TAG=     v${PKGVERSION_NOREV}

MAINTAINER=     pkgsrc-users@NetBSD.org
HOMEPAGE=       https://github.com/cpuguy83/go-md2man
COMMENT=        Converts markdown into roff (man pages)
LICENSE=        mit

.include "go-modules.mk"
.include "../../lang/go/go-module.mk"
.include "../../mk/bsd.pkg.mk"

There’s quite a strong resemblance, don’t you think????

Conclusion

That wraps up this arc on pkgsrc, and iMil is already proposing new adventures, but I must admit I’m really starting to appreciate pkgsrc and its logic. Because here’s the thing: EVERYTHING in it is elegant, logical, and consistent. And that, I love.

I’ll of course continue to write up my notes on his videos here, so see you very soon!

Rancune.

This post is licensed under CC BY 4.0 by the author.