Here are some tips for dealing with the necessary evil.
Start with identifying dependencies. Avoid assuming, begin experimenting instead. Run diagnostics and document the results. Start simple as early as you can:
Isolate dependencies using virtualisation:
Never rely on implicit existence of system-wide packages - 12factor.net
Packaging your app into a container and trying to reduce the image size is a helpful exercise. It allows you to identify all the files your app depends on. Please read this well-documented journey of the process.
Managing dependencies relies heavily on trust. Most package managers do not support decentralized package hosting for a reason. Packages may become abandoned over time, but the concern lies not only in availability, but in security too. Centralized systems exist to ensure this.
Of course using a centralised service is a potential risk too. The question is which organisation do we trust, and what can we do to mitigate the risk.
One way to mitigate risk is by backing up dependencies. The are two options here: saving artifacts such as binaries and config files, or saving the source code. Whenever feasible, do both.
Another strategy is to prepare potential replacements for certain dependencies. Try building your software on different Linux distribution, compiler, try to swap the key libraries with alternatives.
In most cases we do not have the resources required to build everything from scratch or apply every security update manually. We need to do an evaluation first: identify the software that provides the core value of the product. For embedded systems this unfortunately includes a lot of software: bootloader, os kernel, etc.
Purpose:
Features:
Where to put your dependencies?
Pros:
Cons:
Challenges
Monorepo involves mostly challenges around scaling the organization in a single repo. Polyrepo involves mostly challenges with coordination.
Transition
Splitting one repo is easier than combining multiple repos.
Specify all system component versions in a repository as code.