Lưu ý trước khi bạn đọc phần còn lại: Kịch bản shell hiển thị ở đây chắc chắn không an toàn để sử dụng và được kiểm tra tốt. Sử dụng có nguy cơ của riêng bạn!
Tôi đã viết một kịch bản bash để hoàn thành nhiệm vụ đó. Giả sử thư viện của bạn là lib1 và thư viện bạn cần bao gồm một số ký hiệu là lib2. Tập lệnh bây giờ chạy trong một vòng lặp, nơi đầu tiên nó kiểm tra các ký hiệu không xác định từ lib1 có thể được tìm thấy trong lib2. Sau đó, nó trích xuất các tệp đối tượng tương ứng từ lib2 ar
, đổi tên chúng một chút và đặt chúng vào lib1. Bây giờ có thể có nhiều biểu tượng bị thiếu hơn, bởi vì những thứ bạn đưa vào từ lib2 cần những thứ khác từ lib2, mà chúng tôi chưa bao gồm, vì vậy vòng lặp cần phải chạy lại. Nếu sau một số lần vượt qua của vòng lặp không còn thay đổi nữa, tức là không có tệp đối tượng nào từ lib2 được thêm vào lib1, vòng lặp có thể dừng lại.
Lưu ý rằng các ký hiệu được bao gồm vẫn được báo cáo là không xác định bởi nm
vì vậy tôi đang theo dõi các tệp đối tượng, được thêm vào lib1, để xác định xem vòng lặp có thể dừng được không.
#! /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
Tôi đặt tên cho kịch bản đó libcomp
, vì vậy bạn có thể gọi nó sau đó, ví dụ như với
./libcomp libmylib.a libwhatever.a
nơi libwhthing là nơi bạn muốn bao gồm các biểu tượng từ. Tuy nhiên, tôi nghĩ an toàn nhất là sao chép mọi thứ vào một thư mục riêng trước. Tôi sẽ không tin vào kịch bản của mình rất nhiều (tuy nhiên, nó hoạt động với tôi; tôi có thể đưa libgsl.a vào thư viện số của mình với điều đó và bỏ qua trình chuyển đổi trình biên dịch -lgsl).