At the most basic level, if project A makes use of library B and library C, then you want to be able to verify the behaviour of library B and library C independently and then make use of your conclusions when analysing project A. But if library B and library C use global state then you can't have any confidence that that will work. E.g. if both library B and library C use some other library D that has some global construct, then they will likely interfere with each other.
> Another possibility would be to have subproject-wide global state, and passing a pointer only to library API calls. The latter is also the most realistic case since most libraries take pointer handles.
At that point you're not using global state in the library, which was the point.
> you can always opt for process- or thread-wide global state
That doesn't solve the problem at all.
> Also called "singleton" in OOP circles. Singletons are nothing but global data with nondeterminstic initialization order and superfluous syntax crap on top.
Indeed, and they're seen as bad practice for the same reason as global state in general.