NDK একাধিক C++ রানটাইম লাইব্রেরি সমর্থন করে। এই দস্তাবেজটি এই লাইব্রেরি, জড়িত ট্রেডঅফ এবং কীভাবে সেগুলি ব্যবহার করতে হয় সে সম্পর্কে তথ্য সরবরাহ করে।
C++ রানটাইম লাইব্রেরি
সারণী 1. NDK C++ রানটাইম এবং বৈশিষ্ট্য।
নাম | বৈশিষ্ট্য |
---|---|
libc++ | আধুনিক C++ সমর্থন। |
সিস্টেম | new এবং delete । (r18-এ অপ্রচলিত।) |
কোনটি | কোন হেডার নেই, সীমিত C++। |
libc++ একটি স্ট্যাটিক এবং শেয়ার্ড লাইব্রেরি উভয় হিসাবে উপলব্ধ।
libc++
LLVM-এর libc++ হল C++ স্ট্যান্ডার্ড লাইব্রেরি যা ললিপপ থেকে অ্যান্ড্রয়েড ওএস ব্যবহার করে আসছে এবং NDK r18 হল NDK-এ উপলব্ধ একমাত্র STL।
C++ ক্ল্যাং-এর ডিফল্ট যেকোন সংস্করণে (বর্তমানে C++14) CMake ডিফল্ট করে, তাই C++17 বা পরবর্তী বৈশিষ্ট্যগুলি ব্যবহার করার জন্য আপনাকে আপনার CMakeLists.txt
ফাইলে উপযুক্ত মান CMAKE_CXX_STANDARD
সেট করতে হবে। আরো বিস্তারিত জানার জন্য CMAKE_CXX_STANDARD
এর জন্য CMake ডকুমেন্টেশন দেখুন।
ndk-build ডিফল্টরূপে ক্ল্যাং করার সিদ্ধান্তও ছেড়ে দেয়, তাই ndk-build ব্যবহারকারীদের -std=c++17
বা এর পরিবর্তে যা খুশি যোগ করতে APP_CPPFLAGS
ব্যবহার করা উচিত।
libc++-এর জন্য শেয়ার করা লাইব্রেরি হল libc++_shared.so
, এবং স্ট্যাটিক লাইব্রেরি হল libc++_static.a
। সাধারণ ক্ষেত্রে ব্যবহারকারীর জন্য প্রয়োজন অনুসারে বিল্ড সিস্টেম এই লাইব্রেরিগুলি ব্যবহার এবং প্যাকেজিং পরিচালনা করবে। অস্বাভাবিক ক্ষেত্রে বা আপনার নিজস্ব বিল্ড সিস্টেম প্রয়োগ করার সময়, বিল্ড সিস্টেম রক্ষণাবেক্ষণকারী নির্দেশিকা বা অন্যান্য বিল্ড সিস্টেম ব্যবহারের জন্য নির্দেশিকা দেখুন।
এলএলভিএম প্রকল্পটি এলএলভিএম ব্যতিক্রম সহ অ্যাপাচি লাইসেন্স v2.0 এর অধীনে রয়েছে। আরও তথ্যের জন্য, লাইসেন্স ফাইলটি দেখুন।
সিস্টেম
সিস্টেম রানটাইম /system/lib/libstdc++.so
কে নির্দেশ করে। এই লাইব্রেরিটিকে GNU এর পূর্ণ বৈশিষ্ট্যযুক্ত libstdc++ এর সাথে বিভ্রান্ত করা উচিত নয়। অ্যান্ড্রয়েডে, libstdc++ শুধু new
এবং delete
। একটি পূর্ণ বৈশিষ্ট্যযুক্ত C++ স্ট্যান্ডার্ড লাইব্রেরির জন্য libc++ ব্যবহার করুন।
সিস্টেম C++ রানটাইম মৌলিক C++ রানটাইম ABI-এর জন্য সমর্থন প্রদান করে। মূলত, এই লাইব্রেরি new
এবং delete
দেয়। NDK-তে উপলব্ধ অন্যান্য বিকল্পগুলির বিপরীতে, ব্যতিক্রম পরিচালনা বা RTTI-এর জন্য কোনও সমর্থন নেই।
C লাইব্রেরি হেডার যেমন <cstdio>
-এর জন্য C++ র্যাপার ছাড়াও কোনো স্ট্যান্ডার্ড লাইব্রেরি সমর্থন নেই। আপনি যদি একটি STL চান তবে এই পৃষ্ঠায় উপস্থাপিত অন্যান্য বিকল্পগুলির মধ্যে একটি ব্যবহার করা উচিত।
কোনটি
কোনো STL না থাকার বিকল্পও আছে। সেই ক্ষেত্রে কোন লিঙ্কিং বা লাইসেন্সিং প্রয়োজনীয়তা নেই। কোন C++ স্ট্যান্ডার্ড হেডার উপলব্ধ নেই।
একটি C++ রানটাইম নির্বাচন করা
সিমেক
CMake-এর জন্য ডিফল্ট হল c++_static
।
আপনি আপনার মডিউল-স্তরের build.gradle
ফাইলে ANDROID_STL
ভেরিয়েবল ব্যবহার করে c++_shared
, c++_static
, none
, বা system
নির্দিষ্ট করতে পারেন। আরও জানতে, CMake-এ ANDROID_STL- এর ডকুমেন্টেশন দেখুন।
ndk-বিল্ড
ndk-build-এর জন্য ডিফল্ট none
।
আপনি আপনার Application.mk ফাইলে APP_STL
ভেরিয়েবল ব্যবহার করে c++_shared
, c++_static
, none
, বা system
নির্দিষ্ট করতে পারেন। যেমন:
APP_STL := c++_shared
ndk-build আপনাকে আপনার অ্যাপের জন্য শুধুমাত্র একটি রানটাইম নির্বাচন করতে দেয় এবং শুধুমাত্র Application.mk এ করতে পারে।
সরাসরি ঝনঝন ব্যবহার করুন
আপনি যদি সরাসরি আপনার নিজস্ব বিল্ড সিস্টেমে ক্ল্যাং ব্যবহার করেন, তাহলে ক্ল্যাং++ ডিফল্টরূপে c++_shared
ব্যবহার করবে। স্ট্যাটিক ভেরিয়েন্ট ব্যবহার করতে, আপনার লিঙ্কার ফ্ল্যাগে -static-libstdc++
যোগ করুন। উল্লেখ্য যে যদিও বিকল্পটি ঐতিহাসিক কারণে "libstdc++" নামটি ব্যবহার করে, এটি libc++ এর জন্যও সঠিক।
গুরুত্বপূর্ণ বিবেচনা
স্ট্যাটিক রানটাইম
যদি আপনার অ্যাপ্লিকেশনের সমস্ত নেটিভ কোড একটি একক ভাগ করা লাইব্রেরিতে থাকে, তাহলে আমরা স্ট্যাটিক রানটাইম ব্যবহার করার পরামর্শ দিই। এটি লিঙ্কারকে যতটা সম্ভব অব্যবহৃত কোড ইনলাইন করতে এবং ছাঁটাই করতে দেয়, যার ফলে সবচেয়ে অপ্টিমাইজ করা এবং সবচেয়ে ছোট অ্যাপ্লিকেশন সম্ভব হয়। এটি অ্যান্ড্রয়েডের পুরানো সংস্করণগুলিতে প্যাকেজ ম্যানেজার এবং ডায়নামিক লিঙ্কার বাগগুলি এড়ায় যা একাধিক ভাগ করা লাইব্রেরি পরিচালনা করা কঠিন এবং ত্রুটি-প্রবণ করে তোলে।
এটি বলেছিল, C++-এ, একটি একক প্রোগ্রামে একই ফাংশন বা বস্তুর একাধিক অনুলিপি সংজ্ঞায়িত করা নিরাপদ নয়। এটি সি++ স্ট্যান্ডার্ডে উপস্থিত ওয়ান ডেফিনিশন রুলের একটি দিক।
একটি স্ট্যাটিক রানটাইম (এবং সাধারণভাবে স্ট্যাটিক লাইব্রেরি) ব্যবহার করার সময়, ঘটনাক্রমে এই নিয়মটি ভঙ্গ করা সহজ। উদাহরণস্বরূপ, নিম্নলিখিত অ্যাপ্লিকেশন এই নিয়ম ভঙ্গ করে:
# Application.mk
APP_STL := c++_static
# Android.mk
include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo.cpp
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := bar
LOCAL_SRC_FILES := bar.cpp
LOCAL_SHARED_LIBRARIES := foo
include $(BUILD_SHARED_LIBRARY)
এই পরিস্থিতিতে, STL, সহ এবং গ্লোবাল ডেটা এবং স্ট্যাটিক কনস্ট্রাক্টর উভয় লাইব্রেরিতে উপস্থিত থাকবে। এই অ্যাপ্লিকেশনটির রানটাইম আচরণ অনির্ধারিত, এবং অনুশীলনে ক্র্যাশগুলি খুব সাধারণ। অন্যান্য সম্ভাব্য সমস্যা অন্তর্ভুক্ত:
- একটি লাইব্রেরিতে মেমরি বরাদ্দ করা হয়েছে এবং অন্যটিতে মুক্ত করা হয়েছে, যার ফলে মেমরি লিকেজ বা হিপ দুর্নীতি হয়।
-
libfoo.so
এ উত্থাপিত ব্যতিক্রমগুলিlibbar.so
এ ধরা পড়েনি, যার ফলে আপনার অ্যাপ ক্র্যাশ হয়ে যাচ্ছে। -
std::cout
এর বাফারিং সঠিকভাবে কাজ করছে না।
জড়িত আচরণগত সমস্যাগুলির বাইরে, স্ট্যাটিক রানটাইমকে একাধিক লাইব্রেরিতে লিঙ্ক করা প্রতিটি ভাগ করা লাইব্রেরিতে কোডটি নকল করবে, আপনার অ্যাপ্লিকেশনের আকার বাড়িয়ে দেবে।
সাধারণভাবে, আপনি শুধুমাত্র C++ রানটাইমের একটি স্ট্যাটিক বৈকল্পিক ব্যবহার করতে পারেন যদি আপনার অ্যাপ্লিকেশনে একটি এবং শুধুমাত্র একটি শেয়ার করা লাইব্রেরি থাকে।
শেয়ার করা রানটাইম
যদি আপনার অ্যাপ্লিকেশনটিতে একাধিক ভাগ করা লাইব্রেরি অন্তর্ভুক্ত থাকে, তাহলে আপনার libc++_shared.so
ব্যবহার করা উচিত।
অ্যান্ড্রয়েডে, NDK দ্বারা ব্যবহৃত libc++ OS-এর অংশের মতো নয়। এটি NDK ব্যবহারকারীদের সর্বশেষ libc++ বৈশিষ্ট্যগুলিতে অ্যাক্সেস দেয় এবং Android এর পুরানো সংস্করণগুলিকে লক্ষ্য করার সময়ও বাগ সংশোধন করে। ট্রেড-অফ হল আপনি যদি libc++_shared.so
ব্যবহার করেন তবে আপনাকে অবশ্যই এটি আপনার অ্যাপে অন্তর্ভুক্ত করতে হবে। আপনি যদি Gradle এর সাথে আপনার অ্যাপ্লিকেশন তৈরি করেন তবে এটি স্বয়ংক্রিয়ভাবে পরিচালনা করা হয়।
অ্যান্ড্রয়েডের পুরানো সংস্করণগুলিতে প্যাকেজ ম্যানেজার এবং ডায়নামিক লিঙ্কারে বাগ ছিল যার কারণে নেটিভ লাইব্রেরিগুলির ইনস্টলেশন, আপডেট এবং লোডিং অবিশ্বস্ত হয়। বিশেষ করে, যদি আপনার অ্যাপটি Android 4.3 (Android API লেভেল 18) এর আগে Android এর একটি সংস্করণকে লক্ষ্য করে এবং আপনি libc++_shared.so
ব্যবহার করেন, তাহলে আপনাকে এটির উপর নির্ভরশীল অন্য কোনো লাইব্রেরির আগে শেয়ার করা লাইব্রেরি লোড করতে হবে।
ReLinker প্রকল্পটি সমস্ত পরিচিত নেটিভ লাইব্রেরি লোডিং সমস্যার জন্য সমাধানের প্রস্তাব দেয় এবং সাধারণত আপনার নিজের সমাধান লেখার চেয়ে এটি একটি ভাল পছন্দ।
প্রতি অ্যাপে একটি STL
ঐতিহাসিকভাবে NDK libc++ ছাড়াও GNU libstdc++ এবং STLport সমর্থন করে। যদি আপনার অ্যাপ্লিকেশনটি পূর্বনির্মাণকৃত লাইব্রেরির উপর নির্ভর করে যেগুলি আপনার অ্যাপ্লিকেশন তৈরি করতে ব্যবহৃত একটি এনডিকে থেকে ভিন্ন একটি লাইব্রেরি তৈরি করা হয়েছিল, তাহলে আপনাকে এটি একটি সামঞ্জস্যপূর্ণ পদ্ধতিতে তা নিশ্চিত করতে হবে।
একটি অ্যাপ্লিকেশন একটির বেশি C++ রানটাইম ব্যবহার করা উচিত নয়। বিভিন্ন STL একে অপরের সাথে সামঞ্জস্যপূর্ণ নয় । উদাহরণ হিসেবে, libc++-এ std::string
এর বিন্যাস gnustl-এর মতো নয়। একটি STL এর বিরুদ্ধে লিখিত কোড অন্যটির বিরুদ্ধে লিখিত বস্তু ব্যবহার করতে সক্ষম হবে না। এটি একটি উদাহরণ মাত্র; অসঙ্গতি অনেক।
এই নিয়ম আপনার কোড অতিক্রম প্রসারিত. আপনার সমস্ত নির্ভরতা অবশ্যই একই STL ব্যবহার করবে যা আপনি নির্বাচন করেছেন। আপনি যদি STL ব্যবহার করে এবং প্রতি STL একটি লাইব্রেরি প্রদান না করে এমন একটি বন্ধ উৎসের তৃতীয়-পক্ষ নির্ভরতার উপর নির্ভর করেন, তাহলে STL-এ আপনার কোনো পছন্দ নেই। আপনার নির্ভরতা হিসাবে আপনাকে অবশ্যই একই STL ব্যবহার করতে হবে।
এটা সম্ভব যে আপনি দুটি পারস্পরিক বেমানান লাইব্রেরির উপর নির্ভর করবেন। এই পরিস্থিতিতে একমাত্র সমাধান হল একটি নির্ভরতা বাদ দেওয়া বা রক্ষণাবেক্ষণকারীকে অন্য STL এর বিপরীতে নির্মিত একটি লাইব্রেরি প্রদান করতে বলা।
C++ ব্যতিক্রম
C++ ব্যতিক্রমগুলি libc++ দ্বারা সমর্থিত, কিন্তু ndk-build-এ ডিফল্টরূপে অক্ষম করা হয়। এর কারণ হল ঐতিহাসিকভাবে C++ ব্যতিক্রম NDK-তে উপলব্ধ ছিল না। CMake এবং স্বতন্ত্র টুলচেইনে C++ ব্যতিক্রমগুলি ডিফল্টরূপে সক্রিয় থাকে।
ndk-build-এ আপনার সম্পূর্ণ অ্যাপ্লিকেশন জুড়ে ব্যতিক্রমগুলি সক্ষম করতে, আপনার Application.mk ফাইলে নিম্নলিখিত লাইনটি যোগ করুন:
APP_CPPFLAGS := -fexceptions
একটি একক ndk-বিল্ড মডিউলের জন্য ব্যতিক্রমগুলি সক্ষম করতে, এর Android.mk- এ প্রদত্ত মডিউলে নিম্নলিখিত লাইনটি যুক্ত করুন:
LOCAL_CPP_FEATURES := exceptions
বিকল্পভাবে, আপনি ব্যবহার করতে পারেন:
LOCAL_CPPFLAGS := -fexceptions
আরটিটিআই
ব্যতিক্রমগুলির মতো, RTTI libc++ দ্বারা সমর্থিত, কিন্তু ndk-build-এ ডিফল্টরূপে নিষ্ক্রিয় করা হয়। CMake এবং স্বতন্ত্র টুলচেইনে ডিফল্টরূপে RTTI সক্রিয় থাকে।
ndk-build-এ আপনার পুরো অ্যাপ্লিকেশন জুড়ে RTTI সক্ষম করতে, আপনার Application.mk ফাইলে নিম্নলিখিত লাইনটি যোগ করুন:
APP_CPPFLAGS := -frtti
একটি একক ndk-বিল্ড মডিউলের জন্য RTTI সক্ষম করতে, এর Android.mk- এ প্রদত্ত মডিউলে নিম্নলিখিত লাইনটি যোগ করুন:
LOCAL_CPP_FEATURES := rtti
বিকল্পভাবে, আপনি ব্যবহার করতে পারেন:
LOCAL_CPPFLAGS := -frtti