Catatan sebelum Anda membaca sisanya: Script shell yang ditampilkan di sini tentu tidak aman untuk digunakan dan diuji dengan baik. Gunakan dengan risiko Anda sendiri!
Saya menulis skrip bash untuk menyelesaikan tugas itu. Misalkan perpustakaan Anda adalah lib1 dan yang Anda perlu menyertakan beberapa simbol dari adalah lib2. Script sekarang berjalan dalam satu loop, di mana ia pertama kali memeriksa simbol yang tidak terdefinisi dari lib1 dapat ditemukan di lib2. Ini kemudian mengekstrak file objek yang sesuai dari lib2 dengan ar
, mengubah nama mereka sedikit, dan menempatkannya ke lib1. Sekarang mungkin ada lebih banyak simbol yang hilang, karena hal-hal yang Anda sertakan dari lib2 membutuhkan hal-hal lain dari lib2, yang belum kami sertakan, sehingga loop perlu dijalankan kembali. Jika setelah melewati beberapa loop tidak ada perubahan lagi, yaitu tidak ada file objek dari lib2 ditambahkan ke lib1, loop dapat berhenti.
Perhatikan, bahwa simbol yang disertakan masih dilaporkan sebagai tidak terdefinisi oleh nm
, jadi saya melacak file objek, yang ditambahkan ke lib1, sendiri, untuk menentukan apakah loop dapat dihentikan.
#! /bin/bash
lib1="$1"
lib2="$2"
if [ ! -e $lib1.backup ]; then
echo backing up
cp $lib1 $lib1.backup
fi
remove_later=""
new_tmp_file() {
file=$(mktemp)
remove_later="$remove_later $file"
eval $1=$file
}
remove_tmp_files() {
rm $remove_later
}
trap remove_tmp_files EXIT
find_symbols() {
nm $1 $2 | cut -c20- | sort | uniq
}
new_tmp_file lib2symbols
new_tmp_file currsymbols
nm $lib2 -s --defined-only > $lib2symbols
prefix="xyz_import_"
pass=0
while true; do
((pass++))
echo "Starting pass #$pass"
curr=$lib1
find_symbols $curr "--undefined-only" > $currsymbols
changed=0
for sym in $(cat $currsymbols); do
for obj in $(egrep "^$sym in .*\.o" $lib2symbols | cut -d" " -f3); do
echo " Found $sym in $obj."
if [ -e "$prefix$obj" ]; then continue; fi
echo " -> Adding $obj to $lib1"
ar x $lib2 $obj
mv $obj "$prefix$obj"
ar -r -s $lib1 "$prefix$obj"
remove_later="$remove_later $prefix$obj"
((changed=changed+1))
done
done
echo "Found $changed changes in pass #$pass"
if [[ $changed == 0 ]]; then break; fi
done
Saya menamai skrip itu libcomp
, sehingga Anda dapat memanggilnya misalnya dengan
./libcomp libmylib.a libwhatever.a
dari mana libwhever adalah tempat Anda ingin menyertakan simbol. Namun, saya pikir paling aman untuk menyalin semuanya ke direktori yang terpisah terlebih dahulu. Saya tidak akan terlalu mempercayai skrip saya (namun, itu berhasil untuk saya; Saya bisa memasukkan libgsl.a ke dalam perpustakaan numerik saya dengan itu dan meninggalkan saklar kompiler -lgsl).