Skip to content

Instantly share code, notes, and snippets.

@jberryman
Created May 23, 2019 23:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jberryman/47f8c984a2c10b8ca5fb19b5751e0858 to your computer and use it in GitHub Desktop.
Save jberryman/47f8c984a2c10b8ca5fb19b5751e0858 to your computer and use it in GitHub Desktop.
Unpack and repack a library archive file, allowing mapping a script over each contained object
#!/usr/bin/zsh
# Not portable, sorry...
set -e
set -o pipefail
# set -x
# Change to your command. Below we assume that this:
# - deletes (or replaces) the original file
# - the new/replacement object file must be in the same directory as the source file (need not be same name though)
COMMAND="ls -l"
# Calls COMMAND on objects in all archives under this dir, and repacks
TARGET_DIR=$(realpath "$@")
# ...or just take the body of this loop and adapt it if you want to pack a single archive
for f in `find "$TARGET_DIR" -name '*.a' -type f`; do
grep -q "ar archive" <(file "$f") 2>/dev/null || continue
echo -n "$f: "
TMP_DIR=$(mktemp -d)
cd "$TMP_DIR"
# Individual libraries can and do have identical names, which makes this a huge pain.
# We unpack each member into a separate numbered directory, and repack in the same order
O_NUM=1
for cnt nm in `ar t "$f" | sort | uniq -c`; do
for c in {1..$cnt}; do
mkdir $O_NUM
cd $O_NUM
ar xN $c $f $nm
cd ..
((O_NUM++))
done
done
# optimize all objects we just unpacked (some may not be named *.o)
for f in */* ; do "$COMMAND" "$f"; done
# rearchive; use zsh numeric blob qualifier.
ar cq repackaged.a */*(n)
# Backup original
cp --force --backup=numbered "$f" "$f"
cp repackaged.a "$f"
rm -r "$TMP_DIR"
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment