انجمنهای فارسی اوبونتو
کمک و پشتیبانی => برنامهسازی => نویسنده: محمد اعتماددار در 10 امرداد 1392، 03:24 قظ
-
این دستور چه کاری انجام میده؟
gcc -o libfindrtp.so libfindrtp.o packet.o sccp.o sip.o -lpcap
ابهام من درباره سورس برنامه است. که متوجه نمیشم سورس کدام یک از فایلهاست.
و همینطور lpcap- رو متوجه نمیشم که برای چی هست.
-
هیچ کدوم از اینها، سورس برنامه نیستند، بلکه Objectها و Libraryها هستند که توسط این دستور Link میشن.
پارامتر lpcap- هم میگه کتابخانه pcap هم لینک بشه.
-
(دوستان شرمنده، این پست همزمان با جناب nixoen شد، اما دلم نیومد نفرستم)
فایل های .o سورس نیستند. اونها در حقیقت کدهای کامپایل شده ای هستند که هنوز لینک نشدند.
سوییچ l- به کامپایلر میگه که فایل خروجی رو به یک کتابخونه لینک کن. پس lpcap- یعنی فایل خروجی به کتابخونه libpcap.so لینک بشه. libpcap.so کتابخونه ای هست که باهاش میشه پکت های شبکه رو capture کرد. (مثلا tcpdump و برنامه های مشابه از این کتابخونه استفاده می کنند.)
o- اسم فایل خروجی رو مشخص می کنه که اینجا libfindrtp.so هست. (چون این یه کتابخونه هست، به نظرم اینجا یه گزینه shared- کم هست و وارد نشده؟؟؟ اگه اشتباه می کنم دوستان تصحیح کنن)
پس نتیجه اینکه سه تا فایل به نام packet.o sccp.o sip.o به کتابخونه libpcap.so لینک میشن و خروجی توی فایل libfindrtp.so ذخیره میشه.
-
o- اسم فایل خروجی رو مشخص می کنه که اینجا libfindrtp.so هست. (چون این یه کتابخونه هست، به نظرم اینجا یه گزینه shared- کم هست و وارد نشده؟؟؟ اگه اشتباه می کنم دوستان تصحیح کنن)
بله درست میفرمایید. البته من دلیلش رو نمیدونم اما این گزینه shared رو در LDFLAGS قرار دادم (البته فکر کنم قبلش این دستور گزینه shared- رو خودش هم داشت که بعد از اضافه کردن به LDFLAGS که نمیدانم چیست حذفش کردم).
البته بار دوم (بعد از پست شما) به جای قبلی برگردوندمش. و گزینه shared- رو اضافه کردم.
اما یک مشکل هنگام کامپایل بهوجود آمد.
این کُد (به همراه shared-) با خطا مواجه میشه:
gcc -shared -o libfindrtp.so libfindrtp.o packet.o sccp.o sip.o -lpcap
/usr/lib64/gcc/x86_64-slackware-linux/4.7.1/../../../../x86_64-slackware-linux/bin/ld: packet.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
packet.o: could not read symbols: Bad value
collect2: error: ld returned 1 exit status
make: *** [libfindrtp] Error 1
بعد در اینترنت به موارد مشابه که برخوردم گفت که چون شما میخواید یک object بسازید باید از گزینه c- استفاده کنید.
بعد از استفاده از گزینه c- هم به مشکل جدیدی برخوردم:
gcc -shared -c -o libfindrtp.so libfindrtp.o packet.o sccp.o sip.o -lpcap
gcc: warning: libfindrtp.o: linker input file unused because linking not done
gcc: warning: packet.o: linker input file unused because linking not done
gcc: warning: sccp.o: linker input file unused because linking not done
gcc: warning: sip.o: linker input file unused because linking not done
اضافه کردن گزینه c- در اینجا کار درستی هست؟ (فکر میکنم که در کامپایلر نسخه جدید این کُد دچار مشکل شده، در کامپایلرهای خیلی قدیمی حدود سال ۲۰۰۶ «گمان میکنم نسخه ۳.۶» این مشکل وجود ندارد؛ یعنی نیازی به پارامتر c- نبود و بدون اشکال کامپایل میکند.)
-
نکته دیگه ای که من در مورد کامپایل کتابخانه ها فراموش کردم، گزینه fPIC- بود. تمام کتابخانهها باید با این گزینه کامپایل بشن. این گزینه کتابخانه رو با آدرسهای position independent کامپایل میکنه تا کتابخانه از هر جایی در RAM بتونه بارگذاری بشه. پس علاوه بر shared- این گزینه رو هم اضافه کنید. LDFLAGS پارامترهای برنامه linker رو مشخص میکنه، CFLAGS هم پارامترهای خود کامپایلر رو مشخص میکنه. گزینه c- برنامه رو فقط کامپایل میکنه، اما به هیچ چیزی لینک نمیکنه (برنامه linker اجرا نمیشه). توی دستور بالا شما بهش احتیاج ندارید. چون دارید -lpcap رو استفاده میکنید تا برنامه به کتابخانه libpcap لینک بشه. c- برای ایجاد فایلهای object یا همون o. هست، شما در حال کامپایل یک کتابخانه هستید نه object file.