在阅读其余内容之前,请注意:这里显示的shell脚本肯定不安全使用,并且未经良好测试。使用后果自负!
我编写了一个bash脚本来完成该任务。假设您的库是lib1,而您需要包含一些符号的库是lib2。该脚本现在在循环中运行,在该循环中,它首先检查可以在lib2中找到lib1中哪些未定义的符号。然后,使用lib从lib2中提取相应的目标文件,对其进行ar
重命名,然后将其放入lib1中。现在可能会有更多的符号丢失,因为您从lib2中包含的内容需要来自lib2中的其他内容,而我们尚未包含,因此循环需要再次运行。如果经过几次循环后没有任何更改,即没有将lib2中的目标文件添加到lib1中,则循环可以停止。
请注意,所包含的符号仍被报告为undefined nm
,因此,我一直跟踪自己添加到lib1中的目标文件,以确定是否可以停止循环。
#! /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
我给那个脚本起了名字libcomp
,所以你可以调用它,例如
./libcomp libmylib.a libwhatever.a
libwhatever是您要在其中包含符号的位置。但是,我认为将所有内容首先复制到一个单独的目录中是最安全的。我不会太信任我的脚本(但是,它对我有用;我可以将libgsl.a包含在我的数字库中,而不必使用-lgsl编译器开关)。