Ian Wienand writes about Linux internals, dynamic linking, x86 performance, and build and CI tooling such as OpenStack's Zuul and Ansible.
HN commenters engage with his technical posts on dynamic libraries and position-independent code, adding their own notes on performance trade-offs and build practices.
It has an interesting performance impact on calls to dynamic libraries. One alternative approach would be to avoid the indirect calls through not using '-fPIC --shared' when building shared libraries but '-mcmodel=large --shared'. This causes the relocations to happen at the direct calls and not through a GOT.
The obvious drawback that it effectively disables sharing code in memory, it would still allow sharing code on disk though. So it would be a middle ground between the current state in dynamic and static linking.
https://www.technovelty.org/c/position-independent-code-and-x86-64-libraries.html
You may want to consider using 'stamp files'. These are just empty files created via 'touch' to serve as a timestamp that Make can use to determine if a target needs to be rebuilt if the target doesn't correspond to an actual file in the build directory. This is useful for build targets such as running docker-compose build.
See https://www.technovelty.org/tips/the-stamp-idiom-with-make.html
While not as straightforward as on Windows (which isn't developer oriented), it's possible on Linux and standard on most distributions (just look at all the -dbg packages of debian-based distributions). A little googling found these instructions involving objcopy to separate debug symbols:
http://www.technovelty.org/code/debug-info.html