ربط المكتبات الثابتة بالمكتبات الثابتة الأخرى
سؤال
لديّ قطعة صغيرة من الكود تعتمد على العديد من المكتبات الثابتة (A_1-A_N). أرغب في تشغيل هذا الرمز في مكتبة ثابتة وجعله متاحًا لأشخاص آخرين.
مكتبتي الثابتة ، دعنا نسميها x ، تجمع بشكل جيد.
لقد قمت بإنشاء برنامج عينة بسيط يستخدم وظيفة من X ، ولكن عندما أحاول ربطه بـ X ، أحصل على العديد من الأخطاء حول الرموز المفقودة من المكتبات A_1 - A_N.
هل هناك طريقة يمكنني من خلالها إنشاء مكتبة ثابتة جديدة ، Y تحتوي على X وجميع الوظائف التي تحتاجها X (بتات مختارة من A_1 - A_N) ، حتى أتمكن من توزيع Y فقط للأشخاص لربط برامجهم؟
تحديث:
لقد نظرت إلى مجرد إلقاء كل شيء معه AR ومع ذلك ، فإن صنع Mega-Lib ، ينتهي بما في ذلك الكثير من الرموز غير المطلوبة (جميع ملفات .o تبلغ حوالي 700 ميغابايت ، ومع ذلك ، فإن تنفيذًا مرتبطًا بشكل ثابت هو 7 ميغابايت). هل هناك طريقة لطيفة لتضمين فقط ما هو مطلوب بالفعل؟
هذا يبدو مرتبطا ارتباطا وثيقا كيفية الجمع بين عدة مكتبات C/C ++ في واحدة؟.
المحلول
لا ترتبط المكتبات الثابتة مع المكتبات الثابتة الأخرى. الطريقة الوحيدة للقيام بذلك هي استخدام أداة أمين المكتبة/الأرشيف (على سبيل المثال AR على Linux) لإنشاء مكتبة ثابتة واحدة جديدة عن طريق تسلسل المكتبات المتعددة.
تعديل: استجابةً للتحديث الخاص بك ، فإن الطريقة الوحيدة التي أعرفها لتحديد الرموز المطلوبة فقط هي إنشاء المكتبة يدويًا من المجموعة الفرعية لملفات .o التي تحتوي عليها. هذا صعب ، يستغرق وقتًا طويلاً ومعرضًا للخطأ. لست على دراية بأي أدوات للمساعدة في القيام بذلك (لا نقول أنها غير موجودة) ، ولكنها ستجعل مشروعًا مثيرًا للاهتمام لإنتاج واحدة.
نصائح أخرى
إذا كنت تستخدم Visual Studio ثم نعم ، يمكنك القيام بذلك.
تتيح لك أداة Builder Library التي تأتي مع Visual Studio الانضمام إلى المكتبات معًا على سطر الأوامر. لا أعرف بأي طريقة للقيام بذلك في المحرر المرئي.
lib.exe /OUT:compositelib.lib lib1.lib lib2.lib
على Linux أو Mingw ، مع GNU Toolchain:
ar -M <<EOM
CREATE libab.a
ADDLIB liba.a
ADDLIB libb.a
SAVE
END
EOM
ranlib libab.a
من إذا لم تحذف liba.a
و libb.a
, ، يمكنك عمل "أرشيف رفيع":
ar crsT libab.a liba.a libb.a
على Windows ، مع MSVC Toolchain:
lib.exe /OUT:libab.lib liba.lib libb.lib
المكتبة الثابتة هي مجرد أرشيف .o
ملفات الكائن. استخراجهم مع ar
(على افتراض UNIX) وحزمهم مرة أخرى في مكتبة كبيرة واحدة.
بدلا من Link Library Dependencies
في خصائص المشروع ، هناك طريقة أخرى لربط المكتبات في Visual Studio.
- افتح مشروع المكتبة (X) التي تريد دمجها مع المكتبات الأخرى.
- أضف المكتبات الأخرى التي تريدها مع X (انقر بزر الماوس الأيمن ،
Add Existing Item...
). - اذهب إلى ممتلكاتهم وتأكد
Item Type
هوLibrary
سيشمل ذلك المكتبات الأخرى في X كما لو كنت ركض
lib /out:X.lib X.lib other1.lib other2.lib
ملاحظة قبل قراءة الباقي: إن البرنامج النصي Shell الموضح هنا ليس آمنًا للاستخدام واختباره جيدًا. استخدام على مسؤوليتك الخاصة!
كتبت نص باش لإنجاز هذه المهمة. لنفترض أن مكتبتك هي lib1 والواحد التي تحتاج إلى تضمين بعض الرموز من IS lib2. يعمل البرنامج النصي الآن في حلقة ، حيث يتحقق أولاً من الرموز غير المحددة من Lib1 في Lib2. ثم يستخرج ملفات الكائن المقابلة من lib2 مع ar
, ، أعيد تسميةهم قليلاً ، ويضعهم في lib1. الآن قد يكون هناك المزيد من الرموز المفقودة ، لأن الأشياء التي قمت بتضمينها من Lib2 تحتاج إلى أشياء أخرى من Lib2 ، والتي لم نقم بتضمينها بعد ، لذلك تحتاج الحلقة إلى الركض مرة أخرى. إذا لم يعد هناك أي تغييرات بعد بعض التغييرات ، أي لم يتم إضافة ملفات كائن من lib2 إلى lib1 ، يمكن أن تتوقف الحلقة.
لاحظ أنه لا يزال يتم الإبلاغ عن الرموز المشمولة على أنها غير محددة بواسطة 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
حيث libhance هو المكان الذي تريد تضمينه من الرموز. ومع ذلك ، أعتقد أنه من الأكثر أمانًا نسخ كل شيء إلى دليل منفصل أولاً. لن أثق في البرنامج النصي الخاص بي كثيرًا (ومع ذلك ، فقد نجحت بالنسبة لي ؛ يمكنني تضمين libgsl.a في مكتبة الأرقام الخاصة بي مع ذلك واترك مفتاح مترجم lgsl).