If you're anything like me (and let us hope this is not the case) you've come across ar crs
, or, for that matter, ar(1) saying
- s
- Write an object-file index into the archive
[…]. Running ar s on an archive is equivalent to running ranlib on it.
while ranlib(1) (generate an index to an archive
) says
ranlib generates an index to the contents of an archive[…]. The index lists each symbol defined by a member of an archive that is a relocatable object file.
comparing llvm-ar(1)
- s
- This modifier requests that an archive index (or symbol table) be added to the archive, as if using ranlib.
Content description follows.
and llvm-ranlib(1) (manual page for llvm-ranlib 19
, the manual looks like untouched help2man-equivalent output)
OVERVIEWs it exclusively as Generate an index for archives
.
Beside the obvious question (the linker can already read archives and read the symbols out of objects, so why would the archive itself duplicate this),
these are all circular, running ranlib is completely equivalent to executing ar -s
, and s is the default.
Well, s is an XSI extension that just rebuilds the symbol table,
because POSIX.1-2024 (in text that dates back to the X/Open Portability Guide Issue 3 ("xpg3") (1988), inherited directly from the System V Interface Definition ("svid" (1985))) says
When there is at least one object file[…]in the archive, an archive symbol table shall be created[…]. Whenever the ar utility is used to create or update[…]an archive, the symbol table shall be rebuilt.
This is all really clear-cut and agrees with our shared personal experience of having constructed many archives, and not having ranlib
bed them, ever.
Why, then, does the GNU Automake manual say
- AC_PROG_RANLIB
- This is required if any libraries are built in the package.
And when was this last true, if ever?
As expected from the svid wording provenance, versions 1-6 at&t unix, at&t System III unix, and all releases of at&t System V unix ship without ranlib.
Indeed, the svid wording is replicated from Unix System User's Manual, System V, January 1983 (SysVr1), in both ar(1)s, but is not in Unix User's Manual, Release 3.0, June 1980 (SysIII). This also corresponds to the ld(1) wording change from
If any argument is a library, it is searched exactly once at the point it is encountered in the argument list. Only those routines defining an unresolved external reference are loaded. If a routine from a library references another routine in the library, the referenced routine must appear after the referencing routine in the library. Thus the order of programs within libraries is important.
(ibid.), and hence lorder(1) and tsort(1), to
[…]are loaded. The library (archive) symbol table (see ar(4) is searched sequentially with as many passes as are necessary to resolve external references which can be satisfied by library members. Thus, the ordering of library members is unimportant.
(SysVr1), but only in ld(1) for non-pdp-11
(lorder(1) is further declared unneeded, except on the pdp-11).
Later releases
(UNIX programmer's manual, 1986 (SysVr2))
drop the pdp-11 and its specific ld(1)/ar(1); the lorder(1) mention is downgraded to "except onsome(sic) computers".
Conversely, Version 7 at&t unix contains ranlib(1) (convert archives to random libraries
, which explains the bizarre name), which
converts each archive to a form which can be loaded more rapidly by the loader, by adding a table of contents named __.SYMDEF to the beginning of the archive. It uses ar(1) to reconstruct the archive,[…].
(UNIXTM TIME-SHARING SYSTEM: UNIX PROGRAMMER'S MANUAL, Seventh Edition, January, 1979), and the loader instead growing a midpoint of both of the aforementioned:
[…]If a routine from a library references another routine in the library, and the library has not been processed by ranlib(1), the referenced routine must appear after the referencing routine in the library. Thus the order of programs within libraries may be important. If the first member of a library is named `__.SYMDEF', then it is understood to be a dictionary for the library such as produced by ranlib; the dictionary is searched iteratively to satisfy as many references as possible.
(ibid.). ranlib(1) BUGS indict further:
Because generation[…]and randomization[…]are separate, phase errors are possible. The loader ld warns when the modification date of a library is more recent than the creation of its dictionary; but this means you get the warning even if you only copy the library.
any system so utterly limp as to warrant more BUGS than DESCRIPTION
is truly worthy of its stench still lingering 45 years on.
One has to wonder why ar didn't, at worst, finish with exec("ranlib", arc, 0)
.
The csrg Archives, CD-ROM 1: Berkeley Systems 1978-1986, CD-ROM 2: Berkeley Systems 1987-1993, CD-ROM 3: Final Berkeley Releases, and CD-ROM 4: Final /usr/src including SCCS files tell us that 3bsd (December, 1979) is not afflicted by this because it doesn't ship ranlib(1) at all (owing no doubt to shipping a novel vax-specific ld(1) with no support for a symbol table).
4bsd (November, 1980) includes Version 7 at&t unix ranlib(1) (and a very related implementation),
and the ld(1) blurb is similarly related, except the first member should
.
lorder(1) is briefly expanded to note that
The need for lorder may be vitiated by use of ranlib(1), which converts an ordered archive into a randomly accessed library.
.
4.3bsd (April, 1986) calls ranlib(1) preprocess archives for efficient linking
instead
and adds -t (matching make -t) to update the timestamp of the symbol table only.
Archive targets in 4.3bsd-Reno (June, 1990) make are rebuilt based on the timestamp in the symbol table, not that of the archive itself (archives without symbol tables are always rebuilt).
4.4bsd-Lite (June, 1993)'s ranlib(1) is table-of-contents for archive libraries
,
and in spite of no implementation changes, ar(1) is expected to offer a superset of the posix 1003.2 functionality
.
This is because
IEEE P1003.2 Draft 11.2 − September 1991,
Section 6: Software Development Utilities Option
doesn't specify as -s, just requiring that
When an archive consists entirely of valid object files,
the implementation shall format the archive so that it is usable as a library for link editing
,
rationalised because
[…].
historical implementations maintain a symbol table to speed searches, particularly when the archive contains object files. However, future implementors may or may not use a symbol table, and the -s option was removed from this clause to permit implementors freedom of choice.
[…]System V maintain
sthe symbol table without[…]-s, so adding -s (even if it were worded as allowing a no-op) would essentially require all portable applications to use it in all invocations involving libraries.
And being fully usable as a library for link editing
is ensured for libraries without symbol tables by this system just shipping GNU ld,
which understands symbol tables, but can read symbols out of objects just as well.
Naturally, the matter of make(1) remains, and it still always considers untabled archives outdated, but it doesn't even try to claim posix compatibility,
and it's basically a cosmetic issue.
Netbsd 1.1 (make/arch.c revision 1.8 (1995-01-11))
echoes this, saying that
we should not bother with the TOC at all since this is used by 'ar' rules that affect the data contents of the archive, not by ranlib rules, which affect the TOC.
,
except that no-thing has ever used separate ar/ranlib rules,
and every make-file in every distribution heretofore (and hence),
if it runs ranlib at all, does so just after ar anyway.
Indeed, the application of the
lorder(1)-recommended ar cr library `lorder *.o | tsort`
stanza is nigh-universal for library archives anyway, even post-ranlib.
This version of the file is included in 4.4bsd-Lite2 (April, 1994 (actually 1995-06))
as make/arch.c revision 8.3 (95/04/28, christos Updated to the latest version from the Netbsd source
).
Thus, you realistically never really needed to run ranlib, since you were building archives with lorder(1) anyway. But if you weren't, then the efficacious range is [1979-01, 1995-06).
The unfortunate virulence of this is reflected even contemporaneously — upstream reports, and I can validate — that in the SunOS 4→5 1992 transition (4.3bsd→SysV rebase) ranlib was naturally lost, then re-invented as a no-op in 2.5 for compat. This remains in the illumos gate.
So, last even remotely desirable 30 years ago, defined as extraneous by all standards, and also 4.4bsd-Lite2 very clearly includes Netbsd code but no unix genealogical chart shows this?
Nit-pick? Correction? Improvement? Annoying? Cute? Anything?
Mail,
post, or open!