Home / Alt manpages / x86_64-linux-gnu-gcc-ranlib-13(1)

  • x86_64-linux-gnu-gcc-ranlib-13(1)
  • User command
  • linux

Index a GCC 13 Static Library with gcc-ranlib

A static archive without a symbol index still links, right up until the linker cannot find a function you know is in there. x86_64-linux-gnu-gcc-ranlib-13 writes that index: it is a GCC 13 wrapper around ranlib whose only real trick is supplying the GCC plugin option for you.

This guide applies to the installed Ubuntu toolchain checked here: gcc-13 and gcc-13-x86-64-linux-gnu are version 13.3.0-6ubuntu2~24.04.1. The wrapper invokes the ranlib found through PATH, so the exact version printed by the delegated program can differ from the Debian package version. Allow about five minutes if GCC and binutils are already installed.

1. Know what the wrapper changes

The four installed manpage names in this toolchain describe the same program. The wrapper accepts ranlib options and archive arguments, then adds an appropriate --plugin option for GCC 13. It does not compile source, create an archive, or install a library: creating an archive is the job of ar, indexing it is the job of ranlib or the equivalent ar -s.

Check the executable and its delegated version first:

$ command -v x86_64-linux-gnu-gcc-ranlib-13
/usr/bin/x86_64-linux-gnu-gcc-ranlib-13
$ x86_64-linux-gnu-gcc-ranlib-13 --version
GNU ranlib (GNU Binutils) 2.47.20260726
...

Your version text may differ. What matters here is that the command exists and exits successfully. If it is missing, check the installed GCC and cross-toolchain packages before changing PATH.

2. Create a test object

Use a temporary directory so the exercise does not alter a project. This command needs no elevated privileges.

$ workdir=$(mktemp -d)
$ cd "$workdir"
$ cat > answer.c <<'EOF'
int answer(void) { return 42; }
EOF
$ x86_64-linux-gnu-gcc-13 -c answer.c -o answer.o

Checkpoint

answer.o should now exist. A compiler error here concerns the source or compiler, not ranlib. Confirm the target file before continuing:

$ test -f answer.o && echo "object ready"
object ready

3. Make the archive

Create a conventional static library with ar. The r operation replaces or adds members, and c creates the archive without a warning if it is new.

$ x86_64-linux-gnu-ar rcs libanswer.a answer.o
$ x86_64-linux-gnu-ar t libanswer.a
answer.o

If your installation uses a different ar name, inspect the available names with command -v. Do not guess a path in a build script: tool names vary between distributions.

4. Write the symbol index

Run the GCC 13 wrapper against the archive. This changes libanswer.a in place by writing or refreshing its archive index; it does not change answer.o.

$ x86_64-linux-gnu-gcc-ranlib-13 libanswer.a
$ echo $?
0

There is normally no output on success. A non-zero status means the archive could not be read or updated, or that an option was invalid.

Warning

There is no separate undo command for an in-place index update. Keep the original archive, or rebuild it, if a failed operation matters to your workflow.

Use nm to print the archive map. The symbol from answer.o should appear, proving the index names the function a linker can find.

$ x86_64-linux-gnu-nm -s libanswer.a

Archive index:
answer

answer.o:
0000000000000000 T answer

Output formatting can vary with binutils, but look for an Archive index: section and the answer symbol. If it is absent, rerun the wrapper against the exact archive you are inspecting: a frequent trap is updating one copy and linking another.

Finish with a link test. This creates a second temporary executable and makes the result observable:

$ cat > main.c <<'EOF'
int answer(void);
int main(void) { return answer() == 42 ? 0 : 1; }
EOF
$ x86_64-linux-gnu-gcc-13 main.c -L. -lanswer -o check-answer
$ ./check-answer
$ echo $?
0

-L. makes the current temporary directory eligible for library lookup, while -lanswer selects libanswer.a. If the link reports an undefined reference, check the archive name, the library search path and the symbol spelling before blaming the index.

6. Use the extra options

The wrapper passes ranlib options through:

  • --help shows the installed usage.
  • --version shows the delegated binutils version.
  • -D writes deterministic archive metadata: UID, GID and timestamp fields in the symbol-map member become zero, which helps reproducible builds. The local ranlib documentation says this is on by default when binutils was configured for deterministic archives.
  • -U requests the opposite of -D.
$ x86_64-linux-gnu-gcc-ranlib-13 --help
$ x86_64-linux-gnu-gcc-ranlib-13 -D libanswer.a

Do not pass a source file and expect compilation, and do not use this command to add or remove archive members: use the appropriate compiler or ar command for that. Ordinary archive work does not require sudo; elevated privileges can leave root-owned build artefacts that your normal account cannot replace.

Common traps

  • Command not found: confirm the cross compiler tools are installed and inspect PATH. The aliases gcc-ranlib, gcc-ranlib-13 and x86_64-linux-gnu-gcc-ranlib may resolve to the same wrapper, but use the versioned triplet name when a build must select GCC 13 explicitly.
  • No archive index: make sure ar created a real archive and that ranlib received the archive path, not the object path. Run x86_64-linux-gnu-ar t libanswer.a then x86_64-linux-gnu-nm -s libanswer.a.
  • Plugin error: inspect PATH and the GCC installation rather than adding a random --plugin path. The wrapper exists to supply the appropriate plugin argument for its GCC 13 installation.
  • Link still fails: confirm the library is named libanswer.a, that -L points at its directory, and that the object exports the expected symbol. Run nm answer.o to compare the symbol name.

Done means

  • Wrapper works: x86_64-linux-gnu-gcc-ranlib-13 --version exits successfully.
  • Archive complete: it contains the intended object member.
  • Index present: nm -s shows the archive index and expected symbol.
  • Link test passed: a test link and execution return status zero.
  • Cleanup done: the temporary directory was removed with rm -rf -- "$workdir" once the test was complete, using the workdir path, not a guess.