Comment by chubot
5 years ago
I can't think of any reason a linker needs to use many libraries, especially not one that start threads. A linker reads files and writes a file. It's a single-purpose tool, not a monolithic app with many dependencies.
Either way, threads should be controlled by the application and not libraries. Well-written libraries like sqlite and Lua are parameterized by I/O and concurrency. They don't read files and start threads behind your back.
I agree with you on both points but when building large complex applications (or tools!) this stuff tends to unintentionally creep up over time and it’s not fun to debug non-deterministic bugs due to an opaquely broken implicit contract between you and a poorly written library that got pulled in transitively. Sometimes those libraries are unavoidable closed source system libraries (https://bugs.python.org/issue33725) and the issue ends up being not easily fixable. It’s just risk minimization.
It's a moot point since the author already said he's not using fork(), but C and C++ apps don't transitively pull in dependencies, especially in the open source world.
That kind of thinking comes from node.js and Rust as far as I can tell.
There is never ever a situation where a program like GCC or Clang will acquire a third party dependency without a commit that explicitly changes the build system.
The Python example isn't really relevant because Python modules are shared libraries, but a linker doesn't have or need shared library plugins (i.e. dynamically linking against arbitrary machine code at runtime).
Of course C and C++ apps transitively pull in dependencies.
First, pkg-config exists and most projects on Unixy OSes use it these days. It doesn't really make much sense to argue "it all has to be specified on the command-line" when the command-line the developer cares about looks like this:
gcc `pkg-config --cflags gtk+-3.0` -o test test.c `pkg-config --libs gtk+-3.0`
(That adds things like `-lcairo` which aren't at all visible at first glance)
Second, why do you think things like libwayland-client, libfreetype, and libexpat show up in the ldd output? They're certainly not in the pkg-config output.
Likewise, nothing says a library has to bump its major version number when it adds a new backend dependency, which means that a distro may add a transitive dependency through a shared library update that doesn't correspond to you bumping your version.
(You can gain new backend dependencies without even recompiling anything you're responsible for.)
Heck, this post explicitly touches on that disconnect between what you add to your build plan and what ldd lists for C and C++ codebases.
https://wiki.alopex.li/LetsBeRealAboutDependencies
1 reply →
In my example, using Apple’s system carbon libraries at the C level transitively pulls in their multithreading framework. It does happen. Everything that can break will break, that attitude is necessary to build robust software.
Forget libraries, a static linker (back in the day) only needed something like half-a-dozen different syscalls, not even a full userland or anything as bougie as libraries.
(if it's unclear, this is strong agreement with chubot. If you make the problem harder than it has to be, you have only yourself to blame...)