স্থিতিশীল লিঙ্কিং কেবল কিছু লাইব্রেরি


108

জিসিসির সাথে সংযোগ স্থাপন করার সময় আমি কীভাবে স্থিতিশীলভাবে আমার বাইনারিগুলিতে কিছু নির্দিষ্ট গ্রন্থাগারকে লিঙ্ক করতে পারি?

gcc ... -static ...লিঙ্কযুক্ত সমস্ত লাইব্রেরি স্থিতিশীলভাবে লিঙ্ক করার চেষ্টা করে , তবে আমি তাদের কয়েকটিটির স্থিতিশীল সংস্করণ পাইনি (যেমন: libX11)।


উত্তর:


112

gcc -lsome_dynamic_lib code.c some_static_lib.a


5
অবজেক্ট ফাইলগুলির পরে লাইব্রেরিগুলিতে লিঙ্ক করুন - বিশেষত স্থিত লাইব্রেরি। লিঙ্ক এনভায়রনমেন্টের প্রাচীন এবং আধুনিক সংস্করণগুলিতে (নভেম্বর ২০১০-তে সামান্য পুরাতন সংস্করণগুলির স্থিতির বিষয়ে আমি নিশ্চিত নই) code.cফাইলের আগে স্থির লাইব্রেরি তালিকাভুক্তি গ্যারান্টি দেয় যে এতে উপস্থিত চিহ্নগুলি উপেক্ষা করা হবে যদি না main()লাইব্রেরি অবজেক্ট ফাইলগুলির মধ্যে একটিতে একটি ফাংশন।
জোনাথন লেফলার

44
আপনি কিভাবে দম্পতি এটি কাজ করে দয়া করে বিস্তারিত বলুন? কোডের উত্তরগুলি নতুনদের জন্য সহায়ক নয়।
জেবি।

8
@jb ডিফল্ট হিসাবে, gcc লিঙ্কগুলি গতিশীল। আপনি যখন -lome_dynamic_lib ব্যবহার করেন এটি প্রত্যাশার সাথে গতিশীলভাবে সংযুক্ত হয়ে যায়। তবে, যখন gcc স্পষ্টভাবে একটি স্ট্যাটিক লাইব্রেরি দেওয়া হয়, এটি সর্বদা এটি স্ট্যাটিকভাবে লিঙ্ক করার চেষ্টা করবে। প্রতীকগুলি সমাধান হওয়ার ক্রম সম্পর্কে কিছু কৌশলপূর্ণ বিবরণ রয়েছে; আমি কীভাবে এটি কাজ করে তা পুরোপুরি নিশ্চিত নই। আমি শিখেছি, সন্দেহ হলে, লাইব্রেরি পতাকাগুলির ক্রম পুনরায় সাজানোর চেষ্টা করুন :-)
বচ্চারিল

4
যদি আপনি স্থিতির সাথে একটি জিপিএল লাইব্রেরি
হাইবি

1
@ হাইবাম জিপিএল স্থিতিশীল এবং গতিশীল সংযোগের জন্য একইভাবে প্রয়োগ করে
ওসভেইন

50

আপনি ldবিকল্প ব্যবহার করতে পারে-Bdynamic

gcc <objectfiles> -static -lstatic1 -lstatic2 -Wl,-Bdynamic -ldynamic1 -ldynamic2

এর পরে সমস্ত গ্রন্থাগার (স্বয়ংক্রিয়ভাবে জিসিসি দ্বারা সংযুক্ত সিস্টেমগুলি সহ) গতিশীলভাবে সংযুক্ত হবে।


19
-ডাব্লুএল, -বিডিনামিকের জন্য জিএনইউ এলডি প্রয়োজন, সুতরাং জিসিসি সিস্টেম এলডি ব্যবহার করে এমন সিস্টেমগুলিতে এই সমাধান কাজ করে না (যেমন ম্যাক ওএস এক্স)।
পিটিএস

33
gcc objectfiles -o program -Wl,-Bstatic -ls1 -ls2 -Wl,-Bdynamic -ld1 -ld2

আপনি এছাড়াও ব্যবহার করতে পারেন: -static-libgcc -static-libstdc++জিসিসি লাইব্রেরির জন্য পতাকা

মনে রাখবেন যে libs1.soএবং যদি libs1.aউভয়ই বিদ্যমান থাকে তবে লিঙ্কারটি libs1.soআগে -Wl,-Bstaticবা পরে থাকলে তা বেছে নেবে -Wl,-Bdynamic। পাস করতে ভুলবেন না -L/libs1-library-location/কল করার আগে -ls1


1
কমপক্ষে, এই সমাধানটি libgomp বিরুদ্ধে স্থির লিঙ্কে কাজ করে!
জেরুমে

-staticকমান্ডের কোথাও ব্যবহার করা ব্যর্থ হওয়ার সময় এটি আমার পক্ষে ভাল কাজ করে (আমি ধরে নিই যে এটি কেবলমাত্র আমার পছন্দসই গ্রন্থাগারগুলির চেয়ে স্থিতিশীলভাবে আরও জিনিস সংযুক্ত করার চেষ্টা করে)।
nh2

4
বিশেষ দ্রষ্টব্য। ক্রম -Wl,-Bstaticএবং -Wl,-Bdynamicগুরুত্বপূর্ণ।
পাভেল ভ্লাসভ

27

ম্যানপেজ থেকে ld( এটি জিসিসির সাথে কাজ করে না) --staticবিকল্পটি উল্লেখ করে :

আপনি কমান্ড লাইনে একাধিকবার এই বিকল্পটি ব্যবহার করতে পারেন: এটি লাইব্রেরি অনুসন্ধান -l বিকল্পগুলি অনুসন্ধান করে যা এটি অনুসরণ করে।

একটি সমাধান হ'ল --staticকমান্ড লাইনে বিকল্পের আগে আপনার গতিশীল নির্ভরতা স্থাপন করা।

আর একটি সম্ভাবনা হ'ল ব্যবহার না করা --static, তবে পরিবর্তে কোনও নির্দিষ্ট লাইব্রেরির স্থিতিশীলভাবে সংযোগের জন্য স্ট্যাটিক অবজেক্ট ফাইলের (যেমন -l বিকল্প ব্যবহার না করা) সম্পূর্ণ ফাইলের নাম / পথ সরবরাহ করুন। উদাহরণ:

# echo "int main() {}" > test.cpp
# c++ test.cpp /usr/lib/libX11.a
# ldd a.out
linux-vdso.so.1 =>  (0x00007fff385cc000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f9a5b233000)
libm.so.6 => /lib/libm.so.6 (0x00007f9a5afb0000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00007f9a5ad99000)
libc.so.6 => /lib/libc.so.6 (0x00007f9a5aa46000)
/lib64/ld-linux-x86-64.so.2 (0x00007f9a5b53f000)

আপনি উদাহরণে দেখতে পারেন, libX11 , গতিশীলভাবে সংযুক্ত লাইব্রেরির তালিকায় নেই, কারণ এটি স্থিরভাবে সংযুক্ত ছিল।

সাবধান: একটি .soফাইল সর্বদা গতিযুক্ত লিঙ্কযুক্ত, এমনকি একটি পূর্ণ ফাইলের নাম / পাথের সাথে নির্দিষ্ট করা হলেও।


LibX11.a এবং আউটপুট এর মধ্যে সম্পর্ক কী ldd a.out?
রাফি খ্যাচাডৌড়িয়ান

1
আহ আমি দেখি. lddভাগ করা লাইব্রেরিগুলি আউটপুট দেয় এবং libX11 সেই তালিকায় উপস্থিত হয় না।
রাফি খ্যাচাডৌড়িয়ান

এটা পরিষ্কার নয়। আপনি 'এই বিকল্প' এবং 'সেই বিকল্প' বলছেন। কি বিকল্প?
অক্টোপাস

19

সমস্যাটি যা আমি বুঝতে পেরেছি তা নিম্নরূপ। আপনার কয়েকটি গ্রন্থাগার রয়েছে, কিছু স্ট্যাটিক, কিছু গতিশীল এবং কিছু স্থির এবং গতিশীল amic জিসিসি'র ডিফল্ট আচরণটি "বেশিরভাগ গতিশীল" লিঙ্ক করা। এটি হ'ল জিসিসি গতিশীল লাইব্রেরিতে লিঙ্কগুলি সম্ভব হলে কিন্তু অন্যথায় স্থির লাইব্রেরিতে ফিরে যায়। আপনি ব্যবহার করেন, তখন -static বিকল্পে ভালো হচ্ছে gcc আচরণ যথাযথ গতিশীল লাইব্রেরি আছে এমনকি যদি কোন স্ট্যাটিক গ্রন্থাগার খুঁজে পাওয়া যেতে পারে একটি ত্রুটির কথা কেবলমাত্র লিঙ্কের স্ট্যাটিক লাইব্রেরি ও প্রস্থান করে।

আরেকটি বিকল্প, যা আমি বেশ কয়েকবার আকাঙ্ক্ষিত আছে জিসিসি ছিল, আমি কি কল -mostly স্ট্যাটিক এবং মূলত বিপরীত -dynamic (ডিফল্ট)। প্রায়-স্থিতিশীল , যদি এটি বিদ্যমান থাকে তবে স্থির লাইব্রেরিগুলির সাথে লিঙ্ক করতে পছন্দ করলেও ডায়নামিক লাইব্রেরিতে ফিরে যেতে হবে।

এই বিকল্পটি বিদ্যমান নেই তবে এটি নিম্নলিখিত অ্যালগরিদম দিয়ে অনুকরণ করা যেতে পারে:

  1. -স্ট্যাটিক সহ আউট লিঙ্ক কমান্ড লাইন তৈরি করা

  2. ডায়নামিক লিঙ্ক বিকল্পগুলির মধ্যে আইট্রেট করুন।

  3. গ্রন্থাগার পাথ স্তূপাকার, অর্থাত ফর্মের সেই সব বিকল্প -L <lib_dir> একটি পরিবর্তনশীল মধ্যে <lib_path>

  4. প্রতিটি ডায়নামিক লিঙ্ক অপশনের জন্য, যেমন -l <lib_name> ফর্মের জন্য , জিসিসি <lib_path> -প্রিন্ট-ফাইল-নাম = lib <lib_name> .a কমান্ডটি চালান এবং আউটপুট ক্যাপচার করুন।

  5. যদি কমান্ডটি আপনি যা করেছেন তা ব্যতীত অন্য কিছু প্রিন্ট করে তবে এটি স্থির লাইব্রেরির পুরো পথ হবে। স্ট্যাটিক লাইব্রেরির পুরো পথ দিয়ে গতিশীল লাইব্রেরি বিকল্পটি প্রতিস্থাপন করুন।

আপনি পুরো লিঙ্ক কমান্ড লাইনটি প্রক্রিয়া না করা পর্যন্ত ধুয়ে ফেলুন এবং পুনরাবৃত্তি করুন। স্থির লিঙ্ক থেকে বাদ দিতে স্ক্রিপ্টটি গ্রন্থাগারের নামের একটি তালিকাও নিতে পারে।

নিম্নলিখিত বাশ স্ক্রিপ্টটি কৌশলটি করছে বলে মনে হচ্ছে:

#!/bin/bash

if [ $# -eq 0 ]; then
    echo "Usage: $0 [--exclude <lib_name>]. . . <link_command>"
fi

exclude=()
lib_path=()

while [ $# -ne 0 ]; do
    case "$1" in
        -L*)
            if [ "$1" == -L ]; then
                shift
                LPATH="-L$1"
            else
                LPATH="$1"
            fi

            lib_path+=("$LPATH")
            echo -n "\"$LPATH\" "
            ;;

        -l*)
            NAME="$(echo $1 | sed 's/-l\(.*\)/\1/')"

            if echo "${exclude[@]}" | grep " $NAME " >/dev/null; then
                echo -n "$1 "
            else
                LIB="$(gcc $lib_path -print-file-name=lib"$NAME".a)"
                if [ "$LIB" == lib"$NAME".a ]; then
                    echo -n "$1 "
                else
                    echo -n "\"$LIB\" "
                fi
            fi
            ;;

        --exclude)
            shift
            exclude+=(" $1 ")
            ;;

        *) echo -n "$1 "
    esac

    shift
done

echo

উদাহরণ স্বরূপ:

mostlyStatic gcc -o test test.c -ldl -lpthread

আমার সিস্টেমে ফেরত:

gcc -o test test.c "/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/libdl.a" "/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/libpthread.a"

বা একটি বাদ দিয়ে:

mostlyStatic --exclude dl gcc -o test test.c -ldl -lpthread

আমি তখন পাই:

gcc -o test test.c -ldl "/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/libpthread.a"

7

-l:libstatic1.aজিসিসিতে -l বিকল্পের (মাইনাস এল কোলন) বৈকল্পিক এছাড়াও স্ট্যাটিক লাইব্রেরি লিঙ্ক করতে ব্যবহার করা যেতে পারে ( https://stackoverflow.com/a/20728782 ধন্যবাদ ) এটি কি নথিভুক্ত? জিসিসির অফিশিয়াল ডকুমেন্টেশনে নেই (যা ভাগ করা লিবসের ক্ষেত্রেও সঠিক নয়): https://gcc.gnu.org/onlinesocs/gcc/Link-Options.html

-llibrary
-l library 

লিঙ্ক করার সময় লাইব্রেরি নামের গ্রন্থাগারটি অনুসন্ধান করুন। (পৃথক আর্গুমেন্ট হিসাবে লাইব্রেরির সাথে দ্বিতীয় বিকল্পটি কেবল পক্সিক্স কমপ্লায়েন্সের জন্য এবং এটির প্রস্তাব দেওয়া হয় না using) ... একটি -l বিকল্প ব্যবহার করা এবং কোনও ফাইলের নাম নির্দিষ্ট করার মধ্যে পার্থক্য কেবল হ'ল 'লাইব' এবং গ্রন্থাগারের আশেপাশে থাকে '.এ' এবং বেশ কয়েকটি ডিরেক্টরি অনুসন্ধান করে।

বিন্টিলস এলডি ডকটি এটি বর্ণনা করে। -lnameবিকল্পের জন্য অনুসন্ধান করতে হবে libname.soএরপর libname.aও liberal এর সংক্ষিপ্ত রূপ উপসর্গ যোগ করার .so(মুহূর্তে সক্রিয় হলে) বা .aপ্রত্যয়। তবে -l:nameবিকল্পগুলি কেবলমাত্র নির্দিষ্ট নামের জন্য অনুসন্ধান করবে: https://sourceware.org/binutils/docs/ld/Options.html

-l namespec
--library=namespec

namespecলিঙ্কের ফাইলগুলির তালিকার দ্বারা নির্দিষ্ট করা সংরক্ষণাগার বা অবজেক্ট ফাইল যুক্ত করুন। এই বিকল্পটি যে কোনও সময় ব্যবহার করা যেতে পারে। যদি namespecফর্মটি থাকে :filename, ld নামক filenameকোনও ফাইলের জন্য লাইব্রেরির পাথ অনুসন্ধান করবে, অন্যথায় এটি একটি ফাইলের জন্য লাইব্রেরির পাথ অনুসন্ধান করবে libnamespec.a

যে সমস্ত সিস্টেমে ভাগ করা লাইব্রেরিগুলি সমর্থন করে, ld অন্যান্য ফাইলগুলিও অনুসন্ধান করতে পারে libnamespec.a। বিশেষত, ইএলএফ এবং সানোএস সিস্টেমে, ld একটি কল করা লাইব্রেরির জন্য একটি ডিরেক্টরি অনুসন্ধান করবে যাকে বলা হয় libnamespec.soতার অনুসন্ধান করার আগে libnamespec.a। (কনভেনশন দ্বারা, একটি .soএক্সটেনশন একটি ভাগ করা লাইব্রেরি নির্দেশ করে)) নোট করুন যে এই আচরণটি প্রযোজ্য নয় :filename, যা সর্বদা ডাকা একটি ফাইল নির্দিষ্ট করে filename

লিঙ্কার কেবল একটি সংরক্ষণাগারটি একবার অনুসন্ধান করবে, যেখানে এটি কমান্ড লাইনে নির্দিষ্ট করা হয়েছে at সংরক্ষণাগারটি যদি একটি প্রতীককে সংজ্ঞায়িত করে যা কমান্ড লাইনে সংরক্ষণাগারটির আগে উপস্থিত কিছু বস্তুর মধ্যে অপরিবর্তিত ছিল তবে লিঙ্কারটি সংরক্ষণাগার থেকে উপযুক্ত ফাইল (গুলি) অন্তর্ভুক্ত করবে। যাইহোক, কমান্ড লাইনে পরে উপস্থিত কোনও অবজেক্টের একটি অপরিজ্ঞাত প্রতীক লিঙ্কারটিকে পুনরায় সংরক্ষণাগারটি সন্ধান করবে না।

-(লিঙ্কারকে একাধিকবার আর্কাইভগুলি অনুসন্ধান করতে বাধ্য করার উপায়টির বিকল্পটি দেখুন ।

আপনি একই সংরক্ষণাগারটি একাধিক বার কমান্ড লাইনে তালিকাভুক্ত করতে পারেন।

এই ধরণের সংরক্ষণাগার অনুসন্ধান ইউনিক্স লিকারগুলির পক্ষে মানক। তবে, আপনি যদি এআইএক্স-এ এলডি ব্যবহার করে থাকেন তবে মনে রাখবেন এটি এআইএক্স লিঙ্কারের আচরণের থেকে পৃথক।

ভেরিয়েন্টটি -l:namespecবাইনুটিলেস (2007) এর 2.18 সংস্করণ থেকে নথিভুক্ত করা হয়েছে: https://sourceware.org/binutils/docs-2.18/ld/Options.html


এই বিকল্পটি সেখানে কাজ করে বলে মনে হচ্ছে যেখানে সমস্ত কিছু ব্যর্থ হয়। আমরা কেবলমাত্র এমন একটি ক্ষেত্রে হোঁচট খেয়েছি যেখানে আমাদের স্ট্যাটিক-লিংক লাইবজসোনসিপি.এ দরকার ছিল, কারণ আমাদের বিল্ড মেশিনগুলি libjsocpp.so.0 এর সাথে লিঙ্কযুক্ত বাইনারি তৈরি করতে পারে, যেখানে লক্ষ্যযুক্ত ওএস কেবল libjsoncpp.so.1 সরবরাহ করে। যতক্ষণ না আমরা এই পার্থক্যটি পরিষ্কার করতে পারি, এই একমাত্র সমাধান যা আমাদের ক্ষেত্রে যথাযথ ফলাফল পেয়েছিল।
টমাসজ ডব্লিউ

4

কিছু লোডার (লিকার) গতিশীল লোড চালু এবং বন্ধ করার জন্য সুইচ সরবরাহ করে। যদি জিসিসি এই জাতীয় সিস্টেমে চলছে (সোলারিস - এবং সম্ভবত অন্যরা), তবে আপনি প্রাসঙ্গিক বিকল্পটি ব্যবহার করতে পারেন।

আপনি যদি জানেন যে কোন লাইব্রেরিগুলি আপনি স্থিতিশীলভাবে লিঙ্ক করতে চান, আপনি কেবল লিংক লাইনে স্থির লাইব্রেরী ফাইলটি - পুরো পথ দিয়ে নির্দিষ্ট করতে পারেন।


6
যদিও এই উত্তরটি গৃহীত হয়েছিল তা পুরোপুরি সমস্যার সমাধান করে না। @ পেওরো যে সমস্যাটি সমাধান করার চেষ্টা করছেন সেটিকে ব্যাখ্যা করার সাথে সাথে তার কাছে সমস্ত লাইব্রেরির স্থির সংস্করণ নেই যা বোঝায় যে তিনি যতটা সম্ভব লাইব্রেরি স্থিরভাবে সংযুক্ত করতে চান like আমার উত্তর দেখুন।
jcoffland

2

এক লাইনের মধ্যে ডায়নামিক এবং স্ট্যাটিক লাইব্রেরি লিঙ্ক করতে আপনার অবশ্যই ডায়নামিক libs এবং অবজেক্ট ফাইলের পরে স্ট্যাটিক libs লাগাতে হবে :

gcc -lssl main.o -lFooLib -o main

অন্যথায়, এটি কাজ করবে না। এটি বের করতে আমাকে কিছুটা সময় লাগে না।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.