I’ve never been a fan of shards’
postinstall hook and I don’t think I have ever explicitly used it myself. So far, I have been mostly indifferent about it. Lately, however, I’ve realized that probably
postinstall is often more harmful than not.
ameba is a popular development tool and many shards have it listed as a development dependency. When ameba gets installed, its postinstall script builds the ameba binary in
bin/ameba. Every time I run
shards install for a shard using ameba, ameba builds itself. But that’s only useful if you want to contribute to the shard. Most of the time, I don’t need it. And I certainly didn’t ask for it.
Why do I have to wait for ameba to build? Ameba shouldn’t build itself every time it’s installed.
I picked ameba because it’s popular and has stressed my patience many times now. But many other shards are very similar.
For demonstration, I have compiled a list of postinstall scripts used by shards that are indexed on shardbox.org:
Without going into details about individual shards, I’m sure that the postinstall scripts should be avoidable for many of them. For a development tool providing an executable, there are less intrusive options. It could install a script at
bin/ which lazily builds the binary when requested. User experience would be mostly the same. Except now you don’t have to wait on
shards install but the first time you run
bin/ameba (and only if you do that).
In other cases, maybe it would be better to have an actual build system in the dependent shard that takes care of setting up dependencies. This requires a little more effort to configure up front, but it offers much more flexibility. The power to decide what is actually necessary lies with the dependent shard’s build system and what part of that the developer needs. You can use the dependency’s build recipes or use custom ones. You’re not locked into a postinstall script that runs without asking and might not do what you need.
Don’t get me wrong: The general idea is certainly nice: If you install a shard as a dependency, a postinstall script can make sure it’s set up correctly for using the dependency. Shards are distributed as source, so they’re very portable. Binary libraries are not. I think there can be good use cases for postinstall scripts related to installing binary dependencies. But that’s not as trivial as it might seem. Authors ship build instructions that work for their development systems. But postinstall scripts need to be portable across platforms. There’s a lot of variability in what system environment you can expect for a postinstall script: shell, libraries, C toolchain, etc.
I don’t think I have to stress that this is really difficult to do right. And even if it works, it’s fragile. If you don’t run broad integration tests for this, the user with a non-expected system environment is the one who has to deal with it.
Sure, you can just pass
shards install. But that skips all postinstall scripts of all dependencies. Not just the one that’s broken. A broken postinstall script also affects others.
When I look at the examples I referenced above, I’m pretty sure many of them will easily break if applied on anything else than what the developers use as their development system.
I ask you to not use
postinstall. Whatever you want it to do, I’m sure we can do better differently. I’m happy to discuss individual cases - but let’s not dive too deep into edge cases that become bikeshedding.