ভ্লাদিমিরের উত্তরটি আসলে বেশ ভাল, তবে আমি এখানে আরও কিছু পটভূমি জ্ঞান দিতে চাই। হতে পারে একদিন কেউ আমার উত্তর খুঁজে পেয়েছে এবং এটি সহায়ক হতে পারে।
সংকলক উত্স ফাইলগুলিকে (.c, .cc, .cpp, .m) রূপান্তর করে। প্রতি উত্স ফাইলটিতে একটি অবজেক্ট ফাইল রয়েছে। অবজেক্ট ফাইলগুলিতে প্রতীক, কোড এবং ডেটা রয়েছে। অপারেটিং সিস্টেম দ্বারা অবজেক্ট ফাইলগুলি সরাসরি ব্যবহারযোগ্য হয় না।
এখন যখন একটি ডায়নামিক লাইব্রেরি (.dlib), একটি কাঠামো, একটি লোডযোগ্য বান্ডিল (.বান্ডেল) বা এক্সিকিউটেবল বাইনারি তৈরি করা হয়, তখন এই বস্তু ফাইলগুলি লিংক দ্বারা একত্রে সংযুক্ত হয়ে অপারেটিং সিস্টেমটিকে "ব্যবহারযোগ্য" হিসাবে বিবেচনা করা এমন কিছু উত্পাদন করতে পারে, যেমন এটি কিছু করতে পারে সরাসরি একটি নির্দিষ্ট মেমরি ঠিকানায় লোড করুন।
তবে একটি স্ট্যাটিক লাইব্রেরি তৈরি করার সময়, এই সমস্ত অবজেক্ট ফাইলগুলি কেবল একটি বড় সংরক্ষণাগার ফাইলে যুক্ত করা হয়, সুতরাং স্থির লাইব্রেরির (আর্কাইভের জন্য .a) এক্সটেনশন। সুতরাং একটি .a ফাইল অবজেক্ট (.o) ফাইলগুলির সংরক্ষণাগার ছাড়া কিছুই নয়। কোনও টিআরআরচ সংরক্ষণাগার বা কোনও পীড়ন ছাড়াই একটি জিপ সংরক্ষণাগার সম্পর্কে ভাবেন। পুরো একগুচ্ছ .o ফাইলের তুলনায় একক .a ফাইলের অনুলিপি করা খুব সহজ (জাভা-এর মতো, যেখানে আপনি সহজেই বিতরণের জন্য। ক্লাস ফাইলগুলিকে একটি .jar সংরক্ষণাগারে প্যাক করেন)।
কোনও বাইনারিটিকে স্থির গ্রন্থাগারের সাথে সংযুক্ত করার সময় (= সংরক্ষণাগার) লিঙ্কারটি সংরক্ষণাগারে সমস্ত চিহ্নের একটি টেবিল পাবেন এবং পরীক্ষা করুন যে এই চিহ্নগুলির মধ্যে কোনটি বাইনারি দ্বারা রেফারেন্স করা হয়েছে। কেবলমাত্র রেফারেন্সড চিহ্ন সহ অবজেক্ট ফাইলগুলি লিঙ্কার দ্বারা লোড করা হয় এবং লিঙ্কিংয়ের প্রক্রিয়া দ্বারা বিবেচিত হয়। উদাহরণস্বরূপ, যদি আপনার সংরক্ষণাগারে 50 টি অবজেক্ট ফাইল রয়েছে তবে কেবল 20 টি বাইনারি দ্বারা ব্যবহৃত চিহ্ন রয়েছে, কেবল 20 টি লিঙ্কার দ্বারা লোড করা হয়েছে, অন্য 30 টি লিঙ্কিংয়ের প্রক্রিয়াতে সম্পূর্ণ উপেক্ষা করা হবে।
এটি সি এবং সি ++ কোডের জন্য বেশ কার্যকরভাবে কাজ করে, কারণ এই ভাষাগুলি সংকলনের সময় যতটা সম্ভব চেষ্টা করার চেষ্টা করে (যদিও সি ++ তে কিছু রানটাইম-কেবল কিছু বৈশিষ্ট্য রয়েছে)। ওবজ-সি অবশ্য আলাদা ধরণের ভাষা। ওবজে-সি রানটাইম বৈশিষ্ট্যগুলির উপর অনেক বেশি নির্ভর করে এবং অনেকগুলি ওবিজে-সি বৈশিষ্ট্যগুলি কেবলমাত্র রানটাইম-র বৈশিষ্ট্য। ওবজে-সি ক্লাসে সি সি ফাংশন বা গ্লোবাল সি ভেরিয়েবলের সাথে তুলনাযোগ্য চিহ্ন রয়েছে (কমপক্ষে বর্তমান ওজেজে-সি রানটাইমটিতে)। কোনও লিঙ্কার দেখতে পাচ্ছে যে কোনও শ্রেণি রেফারেন্স করা হয়েছে কি না, তাই এটি নির্ধারণ করতে পারে কোনও শ্রেণি ব্যবহৃত হচ্ছে কি না। আপনি যদি কোনও স্ট্যাটিক লাইব্রেরিতে কোনও অবজেক্ট ফাইল থেকে ক্লাস ব্যবহার করেন তবে এই বস্তু ফাইলটি লিঙ্কার দ্বারা লোড করা হবে কারণ লিঙ্কারটি প্রতীকটি ব্যবহৃত হচ্ছে। বিভাগগুলি কেবলমাত্র রানটাইম-এর বৈশিষ্ট্য, বিভাগগুলি ক্লাস বা ফাংশনগুলির মতো চিহ্ন নয় এবং এর অর্থ এটিও হ'ল কোনও লিঙ্কার নির্ধারণ করতে পারে না কোনও বিভাগ ব্যবহার হচ্ছে কি না।
লিঙ্কার যদি ওবজে-সি কোডযুক্ত কোনও বস্তু ফাইল লোড করে তবে এর সমস্ত ওবজ-সি অংশ সর্বদা লিঙ্কিংয়ের পর্যায়ে রয়েছে। সুতরাং যদি বিভাগগুলি যুক্ত কোনও বস্তু ফাইল লোড করা হয় কারণ এটির যে কোনও প্রতীককে "ব্যবহারে" হিসাবে বিবেচনা করা হয় (এটি একটি শ্রেণি হোন, এটি কোনও ফাংশন হোক, এটি একটি বিশ্বব্যাপী পরিবর্তনশীল), বিভাগগুলি পাশাপাশি লোড করা হয় এবং রানটাইম এ উপলব্ধ হবে । তবুও যদি অবজেক্ট ফাইলটি স্বয়ংক্রিয়ভাবে লোড না করা হয় তবে এর বিভাগগুলি রানটাইম এ উপলব্ধ হবে না। একটি বস্তু ফাইল শুধুমাত্র বিভাগ করা হয় না লোড কারণ এটা রয়েছে কোন চিহ্ন linker হবে কি কখনো "ব্যবহার করার ক্ষেত্রে 'বিবেচনা। এবং এটি এখানে পুরো সমস্যা।
বেশ কয়েকটি সমাধান প্রস্তাব করা হয়েছে এবং এখন আপনি কীভাবে জানেন যে এই সমস্ত কীভাবে একসাথে অভিনয় করা হয়, আসুন প্রস্তাবিত সমাধানটির উপর অন্য নজর দেওয়া যাক:
একটি সমাধান -all_load
লিঙ্কার কলটিতে যুক্ত করা। সেই লিঙ্কার পতাকাটি আসলে কী করবে? প্রকৃতপক্ষে এটি লিঙ্কটিকে নীচে বলেছে " আপনি যদি কোনও চিহ্ন ব্যবহার বা না দেখে থাকেন তবে নির্ধারিত সমস্ত আর্কাইভের সমস্ত অবজেক্ট ফাইল লোড করুন " অবশ্যই এটি কাজ করবে; তবে এটি বরং বড় বাইনারিও তৈরি করতে পারে।
আর একটি সমাধান হ'ল -force_load
আর্কাইভের পথ সহ লিংক কলটিতে যুক্ত করা। এই পতাকাটি ঠিক মতো কাজ করে -all_load
তবে কেবলমাত্র নির্দিষ্ট সংরক্ষণাগারটির জন্য। অবশ্যই এটি কাজ করবে।
সর্বাধিক জনপ্রিয় সমাধানটি -ObjC
লিংক কলটিতে যুক্ত করা। সেই লিঙ্কার পতাকাটি আসলে কী করবে? এই পতাকাটি লিঙ্ককারীকে " সমস্ত সংরক্ষণাগার থেকে সমস্ত অবজেক্ট ফাইলগুলি লোড করুন যদি আপনি দেখতে পান যে সেগুলিতে কোনও ওজেজে-সি কোড রয়েছে "। এবং "যে কোনও ওবজ-সি কোড" এর মধ্যে বিভাগ অন্তর্ভুক্ত রয়েছে। এটি পাশাপাশি কাজ করবে এবং এটি কোনও ওজেজে-সি কোডযুক্ত অবজেক্ট ফাইলগুলি লোড করার জন্য বাধ্য করবে না (এগুলি এখনও কেবলমাত্র চাহিদা অনুযায়ী লোড করা হয়)।
আরেকটি সমাধান হ'ল নতুন এক্সকোড বিল্ড সেটিংস Perform Single-Object Prelink
। এই সেটিংটি কী করবে? যদি সক্ষম করা থাকে, সমস্ত অবজেক্ট ফাইল (মনে রাখবেন, উত্স ফাইল প্রতি এক আছে) একক বস্তু ফাইলে একত্রিত হয়ে যায় (এটি আসল সংযোগ নয়, তাই নাম প্রিলিংক ) এবং এই একক অবজেক্ট ফাইল (কখনও কখনও "মাস্টার অবজেক্ট" নামেও পরিচিত ফাইল ") এর পরে সংরক্ষণাগারে যুক্ত করা হয়। এখন যদি মাস্টার অবজেক্ট ফাইলের কোনও প্রতীক ব্যবহার হিসাবে বিবেচিত হয় তবে পুরো মাস্টার অবজেক্ট ফাইলটি ব্যবহার হিসাবে বিবেচিত হয় এবং সুতরাং এর সমস্ত অবজেক্টি-সি অংশ সর্বদা লোড হয়। এবং যেহেতু ক্লাসগুলি সাধারণ প্রতীক, তাই সমস্ত বিভাগ পেতে এই জাতীয় স্ট্যাটিক লাইব্রেরি থেকে একটি ক্লাস ব্যবহার করা যথেষ্ট।
চূড়ান্ত সমাধানটি হ'ল ভ্লাদিমির তার উত্তরের একেবারে শেষে যুক্ত কৌশলটি। যে কোনও উত্স ফাইলে কেবল বিভাগগুলি ঘোষণা করে একটি " জাল প্রতীক " রাখুন । আপনি রানটাইম সময়ে যে কোনও বিভাগ ব্যবহার করতে চান তা নিশ্চিত করে নিন যে আপনি কোনওভাবেই সংকলনকালে নকল প্রতীকটি উল্লেখ করেছেন , কারণ এর ফলে বস্তু ফাইলটি লিংককারী দ্বারা লোড হতে পারে এবং এইভাবে এটিতে সমস্ত ওবিজে-সি কোড রয়েছে। উদাহরণস্বরূপ এটি খালি ফাংশন বডি সহ কোনও ফাংশন হতে পারে (যা ডাকা হওয়ার সময় কিছুই করবে না) বা এটি বিশ্বব্যাপী ভেরিয়েবল অ্যাক্সেস হতে পারে (যেমন বিশ্বব্যাপীint
একবার পড়ুন বা একবার লিখিত, এটি যথেষ্ট)। উপরের অন্যান্য সমস্ত সমাধানের বিপরীতে, এই সমাধানটি রানাইল সময়ে সংকলিত কোডে কোন বিভাগগুলি উপলব্ধ তা নিয়ন্ত্রণ নিয়ন্ত্রণ করে (যদি এটি তাদের লিঙ্কযুক্ত এবং উপলব্ধ হতে চায় তবে এটি প্রতীকটি অ্যাক্সেস করে, অন্যথায় এটি প্রতীকটি অ্যাক্সেস করে না এবং লিঙ্কার উপেক্ষা করবে) এটা)।
এই সব ভাবেন।
ওহ, অপেক্ষা করুন, আরও একটি জিনিস রয়েছে:
লিঙ্কারের একটি বিকল্পের নাম রয়েছে -dead_strip
। এই বিকল্পটি কী করে? যদি লিঙ্কার কোনও অবজেক্ট ফাইলটি লোড করার সিদ্ধান্ত নিয়ে থাকে তবে অবজেক্ট ফাইলের সমস্ত চিহ্নগুলি ব্যবহার করা হোক না কেন, লিঙ্কযুক্ত বাইনারিগুলির অংশ হয়ে যায়। উদাহরণস্বরূপ, কোনও অবজেক্ট ফাইলে 100 টি ফাংশন রয়েছে তবে তাদের মধ্যে কেবল একটি বাইনারি দ্বারা ব্যবহৃত হয়, সমস্ত 100 ফাংশন বাইনারিটিতে এখনও যুক্ত করা হয় কারণ বস্তু ফাইলগুলি সম্পূর্ণরূপে যুক্ত হয় বা সেগুলি মোটেই যুক্ত হয় না। আংশিকভাবে কোনও অবজেক্ট ফাইল যুক্ত করা লিংকারদের দ্বারা সমর্থিত নয়।
তবে, যদি আপনি লিঙ্কারটিকে "মৃত স্ট্রিপ" বলুন, লিঙ্কারটি প্রথমে সমস্ত বস্তুর ফাইলগুলিকে বাইনারি যুক্ত করবে, সমস্ত রেফারেন্স সমাধান করবে এবং শেষ অবধি ব্যবহার না করা প্রতীকগুলির জন্য বাইনারি স্ক্যান করবে (অথবা কেবলমাত্র অন্য চিহ্নগুলির ব্যবহারে নয়) ব্যবহার)। ব্যবহারযোগ্য না হিসাবে পাওয়া সমস্ত প্রতীকগুলি তারপরে অপ্টিমাইজেশন পর্যায়ে অংশ হিসাবে সরানো হবে। উপরের উদাহরণে, 99 অব্যবহৃত ফাংশনগুলি আবার সরানো হয়েছে। এই খুব দরকারী যদি আপনি চান অপশন ব্যবহার করেন -load_all
, -force_load
বা Perform Single-Object Prelink
কারণ এই বিকল্পগুলি সহজে আপ বাইনারি মাপ নাটকীয়ভাবে কিছু ক্ষেত্রে বাজাতে পারবে এবং মৃত Stripping আবার অব্যবহৃত কোড এবং ডেটা মুছে যাবে।
ডেড স্ট্রিপিং সি কোডের জন্য খুব ভাল কাজ করে (উদাঃ যেমন অব্যবহৃত ফাংশন, ভেরিয়েবল এবং ধ্রুবকগুলি প্রত্যাশা অনুযায়ী মুছে ফেলা হয়) এবং এটি সি ++ এর জন্যও বেশ ভাল কাজ করে (যেমন অব্যবহৃত ক্লাস মুছে ফেলা হয়)। এটি নিখুঁত নয়, কিছু ক্ষেত্রে কিছু প্রতীকগুলি সরিয়ে ফেলা ঠিক না হলেও এটি মুছে ফেলা হয় না, তবে বেশিরভাগ ক্ষেত্রে এটি এই ভাষার পক্ষে বেশ ভাল কাজ করে।
ওবজ-সি সম্পর্কে কী? এটি সম্পর্কে ভুলে যাও! ওবজ-সি এর জন্য কোনও মৃত স্ট্রিপিং নেই। যেহেতু ওবজে-সি একটি রানটাইম-বৈশিষ্ট্যযুক্ত ভাষা, তাই সংকলক সংকলনের সময় বলতে পারে না যে প্রতীকটি সত্যই ব্যবহৃত হচ্ছে কিনা। উদাহরণস্বরূপ কোনও ওজজ-সি ক্লাস ব্যবহার করা হয় না যদি সরাসরি কোনও রেফারেন্সিং থাকে তবে সঠিক? ভুল! আপনি গতিতে ক্লাসের নাম সম্বলিত একটি স্ট্রিং তৈরি করতে পারেন, সেই নামের জন্য একটি শ্রেণি নির্দেশকের জন্য অনুরোধ করতে পারেন এবং গতিশীলভাবে বর্গ বরাদ্দ করতে পারেন। যেমন পরিবর্তে
MyCoolClass * mcc = [[MyCoolClass alloc] init];
আমিও লিখতে পারতাম
NSString * cname = @"CoolClass";
NSString * cnameFull = [NSString stringWithFormat:@"My%@", cname];
Class mmcClass = NSClassFromString(cnameFull);
id mmc = [[mmcClass alloc] init];
উভয় ক্ষেত্রেই mmc
"মাইকুলক্লাস" শ্রেণীর কোনও জিনিসের রেফারেন্স , তবে দ্বিতীয় কোডের নমুনায় এই শ্রেণীর সরাসরি কোনও রেফারেন্স পাওয়া যায় না (এমনকি স্ট্যাটিক স্ট্রিং হিসাবে শ্রেণীর নামও নয়)। সবকিছু কেবল রানটাইমের সময় ঘটে। এবং যে যদিও ক্লাস এর দ্বারা আসলে বাস্তব প্রতীক। বিভাগগুলির জন্য এটি আরও খারাপ, কারণ এগুলি এমনকি প্রকৃত প্রতীক নয়।
সুতরাং আপনার যদি কয়েক শতাধিক অবজেক্টের সাথে স্ট্যাটিক লাইব্রেরি থাকে তবে আপনার বেশিরভাগ বাইনারিগুলির মধ্যে কেবল কয়েকটিগুলির প্রয়োজন হয় তবে আপনি উপরের সমাধানগুলি (1) থেকে (4) ব্যবহার না করা পছন্দ করতে পারেন। অন্যথায় আপনি এই সমস্ত শ্রেণীর সমন্বিত খুব বড় বাইনারি দিয়ে শেষ করেন, যদিও তাদের অধিকাংশই ব্যবহৃত হয় না। ক্লাসগুলির জন্য আপনার সাধারণত কোনও বিশেষ সমাধানের প্রয়োজন হয় না কারণ ক্লাসগুলির আসল প্রতীক থাকে এবং যতক্ষণ আপনি এগুলি সরাসরি উল্লেখ করেন (দ্বিতীয় কোডের নমুনায় নয়), লিঙ্কারটি নিজের ব্যবহারটি খুব ভালভাবে চিহ্নিত করবে। বিভাগগুলির জন্য, তবে সমাধান (5) বিবেচনা করুন, কারণ এটি কেবল আপনার সত্যিকারের বিভাগগুলি অন্তর্ভুক্ত করা সম্ভব করে তোলে।
উদাহরণস্বরূপ, আপনি যদি এনএসডিটার জন্য কোনও বিভাগ চান, উদাহরণস্বরূপ এটিতে একটি সংক্ষেপণ / ডিকম্প্রেশন পদ্ধতি যুক্ত করে আপনি একটি শিরোনাম ফাইল তৈরি করতে চান:
// NSData+Compress.h
@interface NSData (Compression)
- (NSData *)compressedData;
- (NSData *)decompressedData;
@end
void import_NSData_Compression ( );
এবং একটি বাস্তবায়ন ফাইল
// NSData+Compress
@implementation NSData (Compression)
- (NSData *)compressedData
{
// ... magic ...
}
- (NSData *)decompressedData
{
// ... magic ...
}
@end
void import_NSData_Compression ( ) { }
এখনই নিশ্চিত হয়ে নিন যে আপনার কোডের যে কোনও জায়গায় import_NSData_Compression()
বলা হয়েছে। এটি কোথায় ডাকা হয় বা কতবার বলা হয় তা বিবেচনা করে না। আসলে এটি আসলেই মোটেও ডাকতে হবে না, লিঙ্কার যদি তাই মনে করে তবে এটি যথেষ্ট। যেমন আপনি নীচের কোডটি আপনার প্রকল্পের যে কোনও জায়গায় রাখতে পারেন:
__attribute__((used)) static void importCategories ()
{
import_NSData_Compression();
// add more import calls here
}
আপনাকে আপনার importCategories()
কোডটিতে কখনও কল করতে হবে না, বৈশিষ্ট্যটি সংকলক এবং লিঙ্কারকে বিশ্বাস করে যে এটি বলা হয়েছিল, এমনকি এটি না থাকলেও।
এবং একটি চূড়ান্ত টিপ:
আপনি যদি -whyload
চূড়ান্ত লিঙ্ক কলটিতে যোগ করেন তবে লিঙ্কারটি বিল্ড লগে মুদ্রণ করবে যা কোন লাইব্রেরি থেকে কোন বস্তুটি এটি ব্যবহার করবে তা কোন চিহ্নের ব্যবহারের কারণে লোড হয়েছে। এটি কেবল ব্যবহৃত হিসাবে বিবেচিত প্রথম প্রতীকটি মুদ্রণ করবে, তবে এটি অবশ্যই অবজেক্ট ফাইলটির ব্যবহারের একমাত্র প্রতীক নয়।