উত্তর:
(আরও বিস্তৃত পাঠ্য পেতে এই উত্তরের ইতিহাস দেখুন, তবে আমি এখন মনে করি পাঠকের পক্ষে আসল কমান্ড লাইনগুলি দেখতে আরও সহজ)।
সাধারণ ফাইলগুলি নীচের সমস্ত কমান্ড দ্বারা ভাগ করা
$ cat a.cpp
extern int a;
int main() {
return a;
}
$ cat b.cpp
extern int b;
int a = b;
$ cat d.cpp
int b;
$ g++ -c b.cpp -o b.o
$ ar cr libb.a b.o
$ g++ -c d.cpp -o d.o
$ ar cr libd.a d.o
$ g++ -L. -ld -lb a.cpp # wrong order
$ g++ -L. -lb -ld a.cpp # wrong order
$ g++ a.cpp -L. -ld -lb # wrong order
$ g++ a.cpp -L. -lb -ld # right order
লিঙ্কারটি বাম থেকে ডানে অনুসন্ধান করে এবং অমীমাংসিত প্রতীকগুলি যেমন যায় তেমন নোট করে। যদি কোনও লাইব্রেরি প্রতীকটি সমাধান করে তবে প্রতীকটি সমাধান করতে that লাইব্রেরির অবজেক্ট ফাইলগুলি লাগে (এক্ষেত্রে libb.a এর বাইরে)।
একে অপরের বিপরীতে স্থির গ্রন্থাগারগুলির নির্ভরতা একই কাজ করে - যে লাইব্রেরিটির জন্য চিহ্নগুলির প্রয়োজন তা অবশ্যই প্রথমে, তারপরে পাঠাগারটি প্রতীককে সমাধান করে।
যদি একটি স্ট্যাটিক লাইব্রেরি অন্য লাইব্রেরির উপর নির্ভর করে তবে অন্য গ্রন্থাগারটি আবার পূর্বের গ্রন্থাগারের উপর নির্ভর করে, সেখানে একটি চক্র রয়েছে। আপনি এটির cyclically নির্ভরশীল লাইব্রেরি পরিক্ষেপ এই সমাধান করতে পারেন -(
এবং -)
যেমন -( -la -lb -)
(আপনি যেমন ডান বন্ধনী, অব্যাহতি প্রয়োজন হতে পারে -\(
এবং -\)
)। সাইক্লিং নির্ভরতাগুলি সমাধান করা হয়েছে তা নিশ্চিত করার জন্য লিঙ্কার তারপরে এই সংযুক্ত লিবটি একাধিকবার অনুসন্ধান করে। অন্যথা, আপনি লাইব্রেরি একাধিক বার, তাই প্রতিটি পরস্পর আগে নির্দিষ্ট করতে পারেন: -la -lb -la
।
$ export LD_LIBRARY_PATH=. # not needed if libs go to /usr/lib etc
$ g++ -fpic -shared d.cpp -o libd.so
$ g++ -fpic -shared b.cpp -L. -ld -o libb.so # specifies its dependency!
$ g++ -L. -lb a.cpp # wrong order (works on some distributions)
$ g++ -Wl,--as-needed -L. -lb a.cpp # wrong order
$ g++ -Wl,--as-needed a.cpp -L. -lb # right order
এটি এখানে একই - লাইব্রেরিগুলিকে অবশ্যই প্রোগ্রামটির অবজেক্ট ফাইলগুলি অনুসরণ করতে হবে। স্ট্যাটিক লাইব্রেরির তুলনায় এখানে পার্থক্য হ'ল আপনার একে অপরের বিরুদ্ধে লাইব্রেরিগুলির নির্ভরতা সম্পর্কে চিন্তা করার দরকার নেই, কারণ গতিশীল লাইব্রেরিগুলি তাদের নির্ভরতাগুলি নিজেরাই সাজিয়ে তোলে ।
কিছু সাম্প্রতিক বিতরণগুলি স্পষ্টতই --as-needed
লিঙ্কার পতাকা ব্যবহারের জন্য ডিফল্ট , যা প্রবর্তন করে যে প্রোগ্রামটির অবজেক্ট ফাইলগুলি গতিশীল লাইব্রেরির আগে উপস্থিত হয়। যদি সেই পতাকাটি পাস হয়ে যায় তবে লিঙ্কারটি এমন লাইব্রেরিগুলিতে লিঙ্ক করবে না যেগুলি কার্যনির্বাহী দ্বারা প্রয়োজনীয় নয় (এবং এটি এটি বাম থেকে ডানে সনাক্ত করে)। আমার সাম্প্রতিক আর্চলিনাক্স বিতরণটি এই পতাকাটি ডিফল্টরূপে ব্যবহার করে না, সুতরাং এটি সঠিক ক্রমটি অনুসরণ না করে ত্রুটি দেয় নি didn't
প্রাক্তনটি তৈরি করার সময় এর b.so
বিরুদ্ধে নির্ভরতা বাদ দেওয়া সঠিক নয় d.so
। তখন লিঙ্ক করার সময় আপনার লাইব্রেরি নির্দিষ্ট করতে হবে a
, তবে a
সত্যিকারের পূর্ণসংখ্যার প্রয়োজন নেই b
, সুতরাং এটির b
নিজস্ব নির্ভরতা সম্পর্কে যত্ন নেওয়া উচিত নয় ।
এর জন্য নির্ভরতাগুলি নির্দিষ্ট করে মিস করতে পারলে এর প্রভাবগুলির উদাহরণ libb.so
$ export LD_LIBRARY_PATH=. # not needed if libs go to /usr/lib etc
$ g++ -fpic -shared d.cpp -o libd.so
$ g++ -fpic -shared b.cpp -o libb.so # wrong (but links)
$ g++ -L. -lb a.cpp # wrong, as above
$ g++ -Wl,--as-needed -L. -lb a.cpp # wrong, as above
$ g++ a.cpp -L. -lb # wrong, missing libd.so
$ g++ a.cpp -L. -ld -lb # wrong order (works on some distributions)
$ g++ -Wl,--as-needed a.cpp -L. -ld -lb # wrong order (like static libs)
$ g++ -Wl,--as-needed a.cpp -L. -lb -ld # "right"
আপনি যদি এখন বাইনারিটির কী নির্ভরশীলতাগুলি খতিয়ে দেখেন তবে আপনি নোট করুন যে বাইনারি নিজেই নির্ভর করে libd
, ঠিক libb
যেমনটি করা উচিত নয়। বাইনারিটি যদি libb
আবার অন্য লাইব্রেরির উপর নির্ভর করে তবে এটি পুনরায় সংযুক্ত করা দরকার, যদি আপনি এটি এভাবে করেন। এবং যদি রানটাইম libb
ব্যবহার করে অন্য কেউ লোড করে dlopen
(ডায়ামিকভাবে প্লাগইন লোড করার কথা ভাবেন), কলটিও ব্যর্থ হবে। সুতরাং "right"
সত্যিই wrong
পাশাপাশি হওয়া উচিত ।
lorder
+ + tsort
না। তবে কখনও কখনও কোনও অর্ডার নেই, যদি আপনার চক্রীয় রেফারেন্স থাকে। তারপরে আপনার সবকিছু সমাধান না হওয়া অবধি লাইব্রেরি তালিকার মধ্যে দিয়ে আপনাকে চক্রটি চালিয়ে যেতে হবে।
জিএনইউ এলডি লিঙ্কার একটি তথাকথিত স্মার্ট লিঙ্কার। এটি পূর্ববর্তী স্ট্যাটিক লাইব্রেরি দ্বারা ব্যবহৃত ফাংশনগুলি ট্র্যাক করে রাখবে, এর অনুসন্ধান সারণী থেকে ব্যবহৃত হয় না এমন ফাংশন স্থায়ীভাবে টস করে দিবে। ফলাফলটি হ'ল যদি আপনি খুব তাড়াতাড়ি একটি স্ট্যাটিক লাইব্রেরি লিঙ্ক করেন, তবে সেই লাইব্রেরির ফাংশনগুলি লিংক লাইনে পরে স্থির লাইব্রেরিতে আর উপলভ্য হবে না।
আদর্শ ইউনিক্স লিঙ্কার বাম থেকে ডানে কাজ করে, তাই আপনার সমস্ত নির্ভরযোগ্য লাইব্রেরি বামদিকে রাখুন এবং যেগুলি লিঙ্ক লাইনের ডানদিকে সেই নির্ভরতাগুলি সন্তুষ্ট করে। আপনি দেখতে পাবেন যে কিছু গ্রন্থাগার অন্যের উপর নির্ভর করে যখন একই সময়ে অন্যান্য গ্রন্থাগারগুলি সেগুলির উপর নির্ভর করে। এটি এখানে জটিল হয়ে ওঠে। যখন বিজ্ঞপ্তি রেফারেন্স আসে, আপনার কোড ঠিক করুন!
স্ট্যাটিক লাইব্রেরিগুলি জড়িত থাকাকালীন জিনিসগুলি কীভাবে জিসিসির সাথে কাজ করে তা পরিষ্কার করার জন্য এখানে একটি উদাহরণ দেওয়া আছে । সুতরাং আসুন ধরে নেওয়া যাক আমাদের নিম্নলিখিত পরিস্থিতিতে আছে:
myprog.o
- main()
উপর নির্ভরশীল ফাংশনlibmysqlclient
libmysqlclient
- স্থিতিশীল, উদাহরণের জন্য (আপনি অবশ্যই ভাগ্যযুক্ত লাইব্রেরি পছন্দ করবেন libmysqlclient
) , কারণ এটি বিশাল; মধ্যে /usr/local/lib
; এবং থেকে স্টাফ উপর নির্ভরশীলlibz
libz
(গতিশীল)আমরা কিভাবে এটি লিঙ্ক করব? (দ্রষ্টব্য: জিসিসি ৪.৩.৪ ব্যবহার করে সাইগউইনকে সংকলনের উদাহরণ)
gcc -L/usr/local/lib -lmysqlclient myprog.o
# undefined reference to `_mysql_init'
# myprog depends on libmysqlclient
# so myprog has to come earlier on the command line
gcc myprog.o -L/usr/local/lib -lmysqlclient
# undefined reference to `_uncompress'
# we have to link with libz, too
gcc myprog.o -lz -L/usr/local/lib -lmysqlclient
# undefined reference to `_uncompress'
# libz is needed by libmysqlclient
# so it has to appear *after* it on the command line
gcc myprog.o -L/usr/local/lib -lmysqlclient -lz
# this works
আপনি যদি -Wl,--start-group
লিঙ্কার পতাকাগুলিতে যুক্ত করেন তবে সেগুলি কোন অর্ডারে রয়েছে বা বৃত্তাকার নির্ভরতা রয়েছে তা বিবেচ্য নয়।
কিউটি তে এর অর্থ যোগ করা:
QMAKE_LFLAGS += -Wl,--start-group
গণ্ডগোলের সাথে প্রচুর সময় সাশ্রয় করে এবং এটি খুব বেশি লিঙ্ক করা ধীরে ধীরে দেখা দেয় না (যা যাইহোক সংকলনের চেয়ে অনেক কম সময় নেয়)।
আপনি -Xlinker বিকল্পটি ব্যবহার করতে পারেন।
g++ -o foobar -Xlinker -start-group -Xlinker libA.a -Xlinker libB.a -Xlinker libC.a -Xlinker -end-group
প্রায় সমান
g++ -o foobar -Xlinker -start-group -Xlinker libC.a -Xlinker libB.a -Xlinker libA.a -Xlinker -end-group
সাবধান!
আমাকে দ্রুত ছড়িয়ে দেওয়ার একটি দ্রুত পরামর্শ: যদি আপনি লিঙ্কারটিকে "জিসিসি" বা "জি ++" হিসাবে আহ্বান করেন, তবে "- স্টার্ট-গ্রুপ" এবং "--end-group" ব্যবহার করে সেই বিকল্পগুলি এর মধ্য দিয়ে যাবে না লিঙ্কার - না এটি কোনও ত্রুটি চিহ্নিত করবে। আপনার যদি গ্রন্থাগারের ক্রমটি ভুল থাকে তবে এটি অপরিজ্ঞাত চিহ্নগুলির সাথে লিঙ্কটি ব্যর্থ করবে।
লিঙ্কারের মাধ্যমে যুক্তিটি পাস করার জন্য জিসিসিকে বলার জন্য আপনাকে এগুলিকে "-Wl, - start-group" ইত্যাদি লিখতে হবে।
কমপক্ষে কিছু প্ল্যাটফর্মে লিঙ্ক অর্ডার অবশ্যই গুরুত্বপূর্ণ। আমি লাইব্রেরিগুলির সাথে সংযুক্ত অ্যাপ্লিকেশনগুলির জন্য ক্র্যাশগুলি ভুল ক্রমে দেখেছি (যেখানে ভুল মানে A এর সাথে বিযুক্ত রয়েছে তবে B এর উপর নির্ভর করে)।
আমি এটি অনেক কিছু দেখেছি, আমাদের কিছু মডিউলগুলি আমাদের কোড প্লাস সিস্টেম এবং তৃতীয় পক্ষের লাইবসের 100 টি লাইব্রেরির চেয়েও বেশি সংযোগ দেয়।
বিভিন্ন লিঙ্কারগুলির উপর নির্ভর করে এইচপি / ইন্টেল / জিসিসি / সান / এসজিআই / আইবিএম / ইত্যাদি আপনি কিছু সমাধান না করা ফাংশন / ভেরিয়েবল ইত্যাদি পেতে পারেন, কিছু প্ল্যাটফর্মে আপনাকে দু'বার লাইব্রেরি তালিকাভুক্ত করতে হবে।
বেশিরভাগ অংশের জন্য আমরা লাইব্রেরিগুলির কাঠামোগত শ্রেণিবিন্যাস, কোর, প্ল্যাটফর্ম, বিমূর্ততার বিভিন্ন স্তর ব্যবহার করি তবে কিছু সিস্টেমে আপনাকে এখনও লিঙ্ক কমান্ডে আদেশ সহ খেলতে হবে।
একবার আপনি কোনও সমাধান ডকুমেন্টটি হিট করেন যাতে পরবর্তী বিকাশকারী এটি আবার কাজ করে না।
আমার প্রবীণ প্রভাষক বলতেন, " উচ্চ সংহতি এবং নিম্ন মিলন ", এটি আজও সত্য।
gcc
আরো-কঠোর আচরণ (অপেক্ষাকৃত) সম্প্রতি পরিবর্তন করা হয়েছে।