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?
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.