Splitting a package in nixpkgs

The quickemu package contains multiple programs, quickemu, quickget. quickemu itself currently can’t be made to work on macOS, but quickget does work and is very useful for downloading distro ISOs, even ones that are years old.

(There’s also macrecovery and windowskey, which are also useful for emulating macOS and Windows systems)

I wrote a patch that fixes the quickemu package build so I can build and run quickget on darwin and would like to make that available in nixpkgs, but the issue is of course that just “fixing” this package makes it misleading to say it’s compatible with darwin, as not all of its programs actually work.

So, I would like to split out a seperate quickget package, but I’m not sure what a good approach for that would be.

Potential solutions

1. Duplicate and modify

Copy the quickemu package, remove everything preventing a darwin build, and remove the quickemu executable after building. Call that new package quickget, done.

What I dislike about this option is that there will be two separate update PRs every time the base repo updates, and changes that are valid in both packages will always have to be duplicated. Builds are also duplicated, though I guess that doesn’t matter in the grand scheme of things. Additionally, if someone mistakenly installs both packages, they’ll get a conflict error, because the binaries of quickget are duplicated between the packages

2. Add a parameter to turn one package into two

Add a parameter (like only-quickget = false) to the package and call it with true in all-packages.nix

This solves code duplication issues and the duplicate PRs, but not most of the other duplications or the conflict errors.

3. Build quickget from quickemu

Build quickget by taking the output of quickemu and simply deleting all files related to quickemu (including man page and so on).

This sounds cool at first, but doesn’t really work (I think), as quickemu will not be marked as compatible with darwin, so quickget can’t be built if it depends on that. Ideally, the dependency also should be the other way around, with quickemu relying on quickget, not the other way around.

4. Have an invisible “parent” derivation

Actually build quickemu and quickget in one derivation, and then derive two packages quickemu and quickget in separate derivations simply by copying only parts of the output, where the first also has a dependency on the latter.

This sounds like it would be the correct solution; only one build, all binaries are on disk only once but frankly I’m unsure if it’s even possible. It would be also annoying if quickget should be brought to additional platforms that quickemu doesn’t even compile on.


So, any idea how I can approach this problem? Is the simplest solution maybe the best one? Or are there some options I’m not even aware of?

1 Like

Option 4 sounds the most reasonable, although it will probably make for messy code to actually pull it off. Then again, code will always be at least as messy as the underlying problem anyway.

1 Like

There’s a 5th option that is widely used: Keep all in the same derivation.

Lots of packages contain multiple programs; they’re simply all included in the bin output.

If one of those programs cannot be made to work, simply don’t include it. Ideally document that clearly in the description of the package, especially if it’s the namesake of the package.

1 Like

As I have seen, there are some work from upstream in order to support Darwin in the future.

So I vote for 2:


{ lib
,  stdenv
,  . . .
, withoutQuickemu ? stdenv.isDarwin
}:

{

patches = lib.optionals withoutQuickemu [
  ./001-remove-quickemu.diff
];

configurePhase = if withoutQuickemu then ''
. . . 
'' else ''
. . . 
''; 

}
2 Likes

Thanks for all your input! I’ll go for that option then, and clearly document in the description that the binary “quickemu” is missing from the output on darwin.

2 Likes