Live data from Hacker News

The .a file is a relic: Why static archives were a bad idea all along

medium.com

51–60 of 136 posts

Re: The .a file is a relic: Why static archives were a bad idea all along

#51
post #47

Earlier quoted context omitted.

> Why things that are solved in other programming ecosystems are impossible in c cpp world, like sane building system This is such an ignorant comment. Most other natively compiled languages have exactly the same concept behind: Object files, Shared Libraries, collection of object and some kind of configuration description of the compilation pipeline. Even high level languages like Rust has that (to some extend). The…

>The fact you (probably) never had to manipulate it directly just mean your higher level work never brought you deep enough where it starts to be a problem. Did you just agree with me that other prog. ecosystems solved the building system challenge?

They solved it by building on top of what C (or LLVM, to be precise) does, not by avoiding or replacing it.

What should C do to solve it? Add another layer of abstraction on top of it? CMake does that and people complain about the extra complexity.

Re: The .a file is a relic: Why static archives were a bad idea all along

#52
post #11

> This design decision at the source level, means that in our linked binary we might not have the logic for the 3DES building block, but we would still have unused decryption functions for AES256. Do people really not know about `-ffunction-sections -fdata-sections` & `-Wl,--gc-sections` (doesn't require LTO)? Why is it used so little when doing statically-linked builds? > Let’s say someone in our library designed th…

Yes, these are really esoteric options, and IIRC GCC's docs say they can be counter-productive.

These options can easily be found by a Google Search or via LLM, whichever one prefers

> they can be counter-productive

Rarely[1]. The only side effect this can have is the constant pools (for ldr rX, [pc, #off] kind of stuff) not being merged, but the negative impact is absolutely minimal (different functions usually use different constants after all!)

([1] assuming elf file format or elf+objcopy output)

There are many other upsides too: you can combine these options with -Wl,-wrap to e.g. prune exception symbols from already-compiled libraries and make the resulting binaries even smaller (depending on platform)

The question is, why are function-sections and data-sections not the default?

It is quite annoying to have to deal with static libs (including standard libraries themselves) that were compiled with neither these flags nor LTO.

Re: The .a file is a relic: Why static archives were a bad idea all along

#53
post #50
post #42

Earlier quoted context omitted.

How can they be expected to learn this, when it is now fashionable to treat C and C++ as if they are scripting languages, shipping header only files? We already had scripting engines for those languages in the 1990's, and the fact they are hardly available nowadays kind of tells of their commercial success, with exception of ROOT.

> How can they be expected to learn this It's the first thing Google and LLMs 'tell' you when you ask about reducing binary size with static libraries. Also LTO does most of the same.

To learn, first one needs to want to learn, which was my whole point.

Re: The .a file is a relic: Why static archives were a bad idea all along

#54
Oh, static linking can be lots of "fun". I ran into this interesting issue once.

1. We have libshared. It's got logging and other general stuff. libshared has static "Foo foo;" somewhere.

2. We link libshared into libfoo and libbar.

3. libfoo and libbar then go into application.

If you do this statically, what happens is that the Foo constructor gets invoked twice, once from libfoo and once from libbar. And also gets destroyed twice.

Re: The .a file is a relic: Why static archives were a bad idea all along

#55
post #38

Earlier quoted context omitted.

Yes, these are really esoteric options, and IIRC GCC's docs say they can be counter-productive.

-ffunction-sections has 750k hits on github. It is among the default flags for opt mode builds in Bazel. There are probably people who consider them defaults, in practice.

Well, C and C++ together have around 7M repos, so about 10%. Actually not entirely esoteric, but Github is only a fraction of the world's codebase and users of these repos probably never looked in the makefile, so I'd say 10% of C/C++ developers knowing about this is a very optimistic estimate.

Re: The .a file is a relic: Why static archives were a bad idea all along

#56
> Something like a “Static Bundle Object” (.sbo) file, that will be closer to a Shared Object (.so) file, than to the existing Static Archive (.a) file.

Is there something missing from .so files that wouldn’t allow them to be used as a basis for static linking? Ideally, you’d only distribute one version of the library that third parties can decide to either link statically or dynamically.

Re: The .a file is a relic: Why static archives were a bad idea all along

#57

It is unclear to me what the author's point is. Its seems to center on the example of DPDK being difficult to link (and it is a bear, I've done it recently). But its full of strawmen and falsehoods, the most notable being the claims about the deficienies of pkg-config. pkg-config works great, it is just very rarely produced correctly by CMake. I have tooling and a growing set of libraries that I'll probably open sour…

yes DLL hell is the issue with dynamic linking -- how many versions of given libraries are required for the various apps you want to install? -- and then you want to upgrade something and it requires yet another version of some library -- there is really no perfect solution to all this

Re: The .a file is a relic: Why static archives were a bad idea all along

#58
post #26

Earlier quoted context omitted.

At a fundamental level I don't understand why we have two separate file types for static and dynamic libraries. It seems primarily for historical reasons? The author proposes introducing a new kind of file that solves some of the problems with .a filed - but we already have a perfectly good compiled library format for shared libraries! So why can't we make gcc sufficiently smart to allow linking against those statica…

Oh, it's even better on the Windows side of things, at least how the MSVC toolchain does it. You can only link a statically-linked .lib library, period. So if you want to statically link against a dynamic library (what a phrase!), you need to have a special version of that .lib library that essentially is just a collection of thunks (in MSVC-specific format) that basically say "oh, you actually want to add symbol Bar…

"So if you want to statically link against a dynamic library (what a phrase!)"

Yes but like an artificially created remarkableness. "dynamic library" should just be "library", and then it's not remarkable at all.

It does seem obvious, and your Delphi example and the other comment wcc example shows, that if an executable can be assembled from .so at run time, then the same thing can also be done at any other time. All the pieces are just sitting there wondering why we're not using them.

Re: The .a file is a relic: Why static archives were a bad idea all along

#59
post #5

> Yet, what if the logger’s ctor function is implemented in a different object file? This is a contrived example akin to "what if I only know the name of the function at runtime and have to dlsym()"? Have a macro that "enables use of" the logger that the API user must place in global scope, so it can write "extern ctor_name;". Or have library specific additions for LDFLAGS to add --undefined=ctor_name There are worka…

> This is a contrived example akin to "what if I only know the name of the function at runtime and have to dlsym()"?

Well, you just do what the standard Linux loader does: iterate through the .so's in your library path, loading them one by one and doing dlsym() until it succeeds :)

Okay, the dynamic loader actually only tries the .so's whose names are explicitly mentioned as DT_NEEDED in the .dynamic section but it still is an interesting design choice that the functions being imported are not actually bound to the libraries; you just have a list of shared objects, and a list of functions that those shared objects, in totality, should provide you with.

Re: The .a file is a relic: Why static archives were a bad idea all along

#60
post #26

Earlier quoted context omitted.

At a fundamental level I don't understand why we have two separate file types for static and dynamic libraries. It seems primarily for historical reasons? The author proposes introducing a new kind of file that solves some of the problems with .a filed - but we already have a perfectly good compiled library format for shared libraries! So why can't we make gcc sufficiently smart to allow linking against those statica…

Because with the current compilation model shared libraries (.so/.dll) are the output of the linker, but static libraries are input for the linker. It is historical baggage, but as it currently stands they're fairly different beasts.

This is succint, thank you.
Post reply on HN