Rationalize `build` and `hack` directories

This also enables incremental builds for dockerized builds.

Fixes #1729
Not sure I understand why `exit` instead of `return`, that makes it impossible to recover from the issue... Is it to be compatible with the errtrace code dumping a stacktrace on exceptions? Otherwise, return 1 on a case where errexit is set should have the same effect as exit 1... But I assume you have a good reason for it so it's probably fine to keep it as is.