Build and Check an LLVM Archive Index with llvm-ranlib-20

A stale symbol index in a static archive is the kind of bug that only shows up at link time, hours after the archive was actually built. llvm-ranlib-20 adds or refreshes that index, then you verify it names the symbols you expect. This guide uses the installed Ubuntu LLVM 20.1.8 build, provided by package llvm-20. Allow about ten minutes if the archive already exists and you only need to check it.

You need a shell, a readable archive made by llvm-ar or a compatible archiver, and permission to write that archive. The normal operation is unprivileged. Do not use sudo merely because the archive belongs to a development toolchain. If it is under a system directory, copy it to a working location or obtain the access required by your local policy before changing it.

1. Confirm the installed tool

Check which executable will run and record its version:

$ command -v llvm-ranlib-20
/usr/bin/llvm-ranlib-20
$ llvm-ranlib-20 --version
Ubuntu LLVM version 20.1.8
  Optimized build.

The package version on the reference system is 1:20.1.8~++20250804090239+87f0227cb601-1~exp1~20250804210352.139. The manual page describes this executable as generating an index for archives. If your version differs, run its own --help before copying these examples into a build script.

2. Inspect the archive before changing it

Set a shell variable to the archive you intend to update and list its members. Replace the example path with a real file. This step reads the archive only:

$ archive=/path/to/libexample.a
$ test -r "$archive" && echo 'archive is readable'
archive is readable
$ llvm-ar-20 t "$archive"
module1.bc
module2.bc

Tip: keep a backup when the archive is valuable or reproducibility matters. The ranlib operation changes the archive, so do not point it at an output that you cannot recreate. A simple backup is reversible:

$ cp --preserve=all "$archive" "$archive.bak"
$ ls -l "$archive" "$archive.bak"

Do not remove the backup until the new index has been checked. Deleting it is an irreversible action and is not needed for the normal workflow.

3. Generate the archive index

Pass the archive as the positional argument:

$ llvm-ranlib-20 "$archive"
$ printf 'exit status: %s\n' "$?"
exit status: 0

A successful run normally prints nothing and returns status 0. The command updates the symbol index in place; it does not list archive members or produce a separate index file. Capture the status immediately if a script needs to distinguish success from failure.

The installed help shows one archive operand in the usage line, llvm-ranlib-20 archive.... Treat each archive as an explicit input rather than relying on a directory wildcard that could include an unintended library.

4. Verify the symbol map

Use LLVM's symbol reader to print the archive map. This verifies more than the ranlib exit status: it shows which symbols the index exposes and which member supplies each one:

$ llvm-nm-20 --print-armap "$archive"
Archive map
answer in answer.bc


answer.bc:
-------- T answer

Your output will contain the symbols from your archive, not necessarily answer. Check that a representative symbol is present and that it points to the expected member. If the map is empty, the archive may contain data without indexable symbols, or it may contain files that this tool does not interpret as expected. Inspect the members and their format before repeating the operation.

Checkpoint: llvm-ar-20 t "$archive" should still list the same members as before, while llvm-nm-20 --print-armap "$archive" should now show the archive map.

5. Choose deterministic or actual metadata

LLVM 20 defaults to deterministic archive metadata. The manual describes -D as using zero for timestamps and user and group IDs, and marks it as the default. This is useful when identical inputs should produce stable archive metadata:

$ llvm-ranlib-20 -D "$archive"
$ printf 'exit status: %s\n' "$?"
exit status: 0

Use -U when the archive must use actual timestamps and user and group IDs:

$ llvm-ranlib-20 -U "$archive"
$ printf 'exit status: %s\n' "$?"
exit status: 0

These options change archive metadata policy; they do not add members or fix missing symbols. Pick one deliberately in a reproducible build and keep that choice consistent with the archive creation step.

6. Handle failures without guessing

There is no archive creation or repair mode in llvm-ranlib-20. If the path is wrong or the file cannot be loaded, the command returns non-zero and reports the problem. For example, the installed command reports a missing input like this:

$ llvm-ranlib-20 /path/to/missing.a
llvm-ranlib-20: error: unable to load '/path/to/missing.a': No such file or directory
$ printf 'exit status: %s\n' "$?"
exit status: 1

Check the path, type and permissions without changing the archive:

$ ls -l "$archive"
$ file "$archive"
$ test -w "$archive" && echo 'archive is writable'

Recovery: if the archive is corrupt, restore the backup or rebuild it from its original object or bitcode members. Do not overwrite the only copy while experimenting. If the symbol map does not contain a required symbol, ranlib cannot create that symbol; check the member contents, linker inputs and the command that created the archive.

7. Keep the command in its proper role

The -h/--help and -V/--version options display information without building an index. The -X option selects archive symbol-table formats when they do not already exist, and the manual labels its 32, 64, 32_64 and any forms as AIX-only. Do not add it to an ordinary Linux build unless an AIX-specific requirement is actually being handled.

For new archives, consider creating the index as part of the archive command with llvm-ar's index operation, where that fits your build. When an archive already exists and needs its index refreshed, llvm-ranlib-20 is the focused command. Neither command compiles sources, adds missing members or links a final executable.

Done means