Please see the disclaimer.

Assumed Audience: The Gentoo authors. And anyone else who would like to laugh at me. 😊

I don’t think this should be posted anywhere, so please don’t.

Epistemic Status: Apologetic and embarrassed. Also, not confident in my checklists at all.

Introduction

I am a Gentoo user. I run Gentoo as my daily driver and server workhorse. I have for at least two years. You would think I would know what I am doing.

And yet…

I made several mistakes packaging software for Gentoo recently.

My bc is in the package repo. I am the maintainer of the package.

When I last updated the package, I copied the wrong file, which was only caught by a Gentoo author.

I guess I was just too tired.

Then I started running my own Matrix server. I needed a desktop client. I settled on Neochat, but the package on Gentoo didn’t have encryption. I decided to change the package to use Olm, the Matrix cryptographic library.

I did so.

Look at that thread. Look at all of the things I got wrong.

  • I got the license wrong for one of the projects.
  • I didn’t wire up tests.
  • I keyworded things wrong.
  • I missed two dependencies.
  • I added an unnecessary dependency.

This was unbelievable. What a clustermess.

Apparently, I just can’t correctly package software for Gentoo.

I’m sorry. I’m really, really sorry.

Yes, I screwed up.

So I’m going to do a postmortem here.

First, I’m going to continue to maintain the packages you have made me responsible for, as well as the upstream bc.

Second, I’m not going to request to add any more packages to Gentoo, except at your request. This includes my own software!

This is because I’m going to vendor my dependencies, and I know you hate that. But I do have reasons below.

Third, because I’m a checklist guy, I’m going to write checklists for adding and updating packages in Gentoo. You’re welcome to rip them, adjust them, and add them to the Gentoo Wiki.

I do not speak for the Gentoo authors. These lists are not official and are almost certainly wrong; check the Gentoo Wiki for official versions, if any.

But I doubt they’ll add them because they probably won’t add value for anyone but me.

Checklist for Updating a Package

  1. Copy an ebuild from the previous version.
  2. Add ~ to all keywords!
  3. Run ebuild <ebuild_file> manifest.
  4. Run ebuild <ebuild_file> compile test install.
  5. Run git add ..
  6. Run pkgcheck scan, fix problems, and repeat as necessary.
  7. Run pkgdev commit.
  8. Run pkgcheck scan --commits.
  9. Double check everything.
  10. Did you actually double-check everything?
  11. Push and open a PR.

Checklist for Adding a Package

  1. Ensure you can manually build the software that you will package, along with its dependecies. This will help you find all of the dependencies and build options.

  2. One-by-one, remove a dependency from the build and see what happens. Add it back before going to the next dependency. This is to ensure that all of the dependencies are needed, or what changes in the build when the dependency is missing.

  3. Create a VM with a virgin Gentoo install. Seriously. This is to help ensure that the dependency list for a package is complete. I added a package that required OpenSSL, which I already had installed, so it built correctly even though I didn’t add OpenSSL as a dependency.

  4. Reread the Basic Guide to Write Gentoo Ebuilds. Select any templates you need.

  5. Review the Ebuild Phase Functions and figure out what you need.

  6. Check the Eclass Reference for any eclasses that you may use for the package and its dependencies.

  7. Follow steps 8-31 for missing dependencies, one at a time, then for the package itself.

  8. Make sure the Copyright header is at the top and has the current year in it.

  9. Make sure you’re using the latest EAPI.

  10. Add inherit <eclass_list> if you are going to use any eclasses.

  11. Set DESCRIPTION.

  12. Set HOMEPAGE.

  13. Set SRC_URI.

  14. Set the license.

  15. Did you double check that the license was correct?

  16. Put SLOT="0". If you need separate slots, give up now.

  17. Add KEYWORDS="~<your_machine_arch>". That’s it. The Gentoo authors do not like it when you add more keywords, and for good reason.

  18. Set IUSE="<list_of_use_flags>". If you don’t already know what USE flags the package needs, you fail. You should have found that out when building the software manually. Go back to the beginning and try again.

  19. Set DEPEND, if any. If you don’t know all of the dependencies already, you fail. Feel ashamed. If you don’t feel ashamed, give up. If you felt proper shame, you can go back to the beginning and try again.

  20. Put

    RDEPEND="
    	$DEPEND
    "
    

    If you need any extra runtime dependencies, you have chosen violence. Stop and reconsider your life choices.

  21. Put any necessary patches, if any. If you don’t know if you need any, fail. If you do know, and you do need patches, you have decided to nuke the world. Set up a lightning rod and yell at Zeus instead.

  22. Add a src_configure() function, if necessary. This will probably be necessary if you have USE flags. Otherwise, cool your jets, dude.

  23. Add any other phase functions. If you need anything other than src_test(), bring a lawyer because you’re going to have to argue your case.

  24. Run ebuild <ebuild_file> manifest.

  25. Run ebuild <ebuild_file> compile test install.

  26. Run git add ..

  27. Run pkgcheck scan, fix problems, and repeat as necessary.

  28. Run pkgdev commit.

  29. Run pkgcheck scan --commits.

  30. Double check everything.

  31. Did you actually double-check everything?

  32. After all dependencies are done, and the package itself is done, push and open a PR.

  33. Be patient. The Gentoo authors are overworked because of idiots like me.

Explanation for Vendoring

Okay, I promised I would explain why I will vendor my dependencies.

I love you, Gentoo authors. I really do. I depend on you, and you have given me a great experience. You do excellent work, and you’ve saved my bacon several times.

So when I criticize you here, I hope it comes off nicely; I’m not trying to lambast you.

Also, I have read Michał’s post.

First reason I will vendor dependencies: it will be easy because I won’t have very many. I have carefully chosen three:

  • SQLite.
  • BearSSL.
  • Libcurl.

I may add one or two more:

  • Zstandard.
  • XXH3.

But I already have a hash, and I may implement a version of Zstandard’s predecessor, lz4, that allows streaming, so I can easily not have those as dependencies.

Yes, I am that obsessive about my dependencies.

Second, I’m going to test each version of my software with the latest versions of all of my dependencies, and every time a new version of a dependency comes out, I will prepare an update to my own just to have the latest version of all dependencies. This will be complete with full testing using the new dependency.

I wouldn’t be surprised if I manage to update my software to the new version before you release the new version of the dependency because I have three, and you have countless packages.

Trying to test my code with multiple sets of versions will become combinatoric. I can’t afford that; it will actually be easier to keep my code up-to-date and to release extra times than to test multiple versions.

Third, I really disagree that dynamic linking is okay; what if an API changes in a way that is incompatible at runtime, but compatible at compile-time?

Examples include:

  • Reording enum items.
  • Reordering function arguments of the same type.
  • Reordering struct fields.

I don’t know how often that happens, but I don’t want my software to cause harm because a dependency was wrong.

So basically, I’m going to vendor because I know my dependencies, will always update my code to the latest versions, and will always release a version of my code to explicitly depend on the latest versions because I only want to test one set of versions.

Of course, if Gentoo ships the latest of my dependencies and wants to undo the bundling, I’ll make that possible. But I will also try to make my code error at compile time if the version does not match the expected version.

Conclusion

I don’t really have a conclusion other than sorry that I screwed up!

Also, love you all; you rock, and I enjoy Gentoo.

Keep calm and compile on.