I'm clearly lacking some basic understanding of how this whole
thing works. How can code that uses the header files from a
library compile *and* link successfully without that library?
In brief: because linking to shared objects (.so's) happens only when
the program is loaded, i.e. at runtime. It doesn't even try to link in
.so's at compile-time - it just takes it on faith that the functions
that you've said will be there (by including a header file) will in fact
be there - so it doesn't know there are unresolved symbols (missing
dependencies) until later, so everything builds without a hitch.