Search code examples
cstatic-librariesbinutils

Getting a list of archive members used while linking a static library


Is there a ready-made solution for getting a list of the archive members that got used (or would be used) while linking in an archive (i.e. a static library)?

Say if I have an object file that provides main and depends on a and b. If I link it against a static lib lib.a, providing a, b, c, d in archive members a.o, b.o, c.o, and d.o respectively, then I would like to get a list with a.o and b.o, either as a side product of linking the library or by running command_to_get_members main.o lib.a

Are there solutions for this or do I need to parse nm outputs and resolve the symbols against the archive members manually?


Solution

  • Here is a suggestion, a script that uses nm (with --defined-only and --undefined-only) to collate which archive objects contain symbols needed by one of the object files specified:

    #!/bin/bash
    export LANG=C LC_ALL=C
    
    objs=()
    libs=()
    for file in "$@" ; do
        [ -r "$file" ] || continue
        if [ "$file" = "${file%.*}.o" ]; then
            objs+=("$file")
        elif [ "$file" = "${file%.*}.a" ]; then
            libs+=("$file")
        else
            printf '%s: Unknown file type. Skipping.\n' "$file" >&2
        fi
    done
    
    nm --defined-only "${libs[@]}" 2>/dev/null | awk -v needsyms="$(nm -u "${objs[@]}" 2>/dev/null | sed -ne 's|^[\t ]*U[\t ]*||p')" \
       'BEGIN {
            split("", objlist)
            n = split(needsyms, symlist)
            for (i = 1; i <= n; i++) need[symlist[i]] = ""
        }
        /\.o:$/ {
            name = $0
            sub(/:$/, "", name)
            next
        }
    
        (NF >= 3) && ($3 in need) {
            need[$3] = name
            objlist[name] = objlist[name] " " $3
        }
    
        END {
            # Print symbols found and their source objects:
            # for (name in need) printf "%s: %s\n", need[name], name
    
            # Print source objects from the archive, with symbols used from it:
            for (name in objlist) printf "%s:%s\n", name, objlist[name]
        }'
    

    Files which have a suffix .a are considered archive objects providing the symbols, and files with suffix .o are object files having undefined symbols.