CMake বিল্ড স্ক্রিপ্ট হল একটি প্লেন টেক্সট ফাইল যার নাম আপনাকে
CMakeLists.txt দিতে হবে এবং এতে CMake আপনার C/C++ লাইব্রেরি তৈরি করতে
যেসব কমান্ড ব্যবহার করে সেগুলি অন্তর্ভুক্ত থাকে। আপনার নেটিভ সোর্সে আগে থেকে CMake বিল্ড স্ক্রিপ্ট না থাকলে, আপনাকে নিজে একটি তৈরি করতে হবে এবং উপযুক্ত CMake কমান্ড
যোগ করতে হবে। CMake কীভাবে ইনস্টল করতে হয় তা জানতে, NDK ও CMake ইনস্টল ও কনফিগার করুন দেখুন।
এই বিভাগে কিছু প্রাথমিক কমান্ডের ব্যাপারে আলোচনা করা হয়েছে যেগুলি আপনার নেটিভ লাইব্রেরি তৈরি করার সময় কোন সোর্স ব্যবহার করতে হবে তা CMake-কে জানানোর জন্য আপনার বিল্ড স্ক্রিপ্টে অন্তর্ভুক্ত করা উচিত। আরও জানতে, CMake কমান্ড সম্পর্কে অফিসিয়াল ডকুমেন্টেশন পড়ুন।
নতুন CMake বিল্ড স্ক্রিপ্ট কনফিগার করার পরে, আপনাকে Gradle কনফিগার করতে হবে যাতে আপনার CMake প্রোজেক্টকে বিল্ড ডিপেন্ডেন্সি হিসেবে অন্তর্ভুক্ত করা যায়, যাতে Gradle আপনার অ্যাপের APK-এর সাথে নেটিভ লাইব্রেরি বিল্ড ও প্যাকেজ করে।
মনে রাখবেন: আপনার প্রোজেক্ট ndk-build ব্যবহার করলে, আপনাকে
CMake বিল্ড স্ক্রিপ্ট তৈরি করতে হবে না। আপনি সহজেই
Gradle কনফিগার
করতে পারবেন যাতে আপনার
Android.mk ফাইলের পাথ প্রদান করে আপনার বর্তমান নেটিভ লাইব্রেরি প্রোজেক্ট অন্তর্ভুক্ত করতে পারেন।
CMake বিল্ড স্ক্রিপ্ট তৈরি করো
আপনার CMake বিল্ড স্ক্রিপ্ট হিসেবে ব্যবহার করতে পারবেন এমন একটি প্লেন টেক্সট ফাইল তৈরি করতে, নিম্নলিখিত ধাপগুলি অনুসরণ করুন:
- IDE-এর বাঁদিকে প্রোজেক্ট প্যানেল খুলুন এবং ড্রপ-ডাউন মেনু থেকে প্রোজেক্ট ভিউ বেছে নিন।
- your-module-এর রুট ডিরেক্টরির উপর ডানদিকের মাউস বোতামে ক্লিক করুন এবং
নতুন > ফাইল বিকল্প বেছে নিন।
মনে রাখবেন: আপনি যেকোনও লোকেশনে বিল্ড স্ক্রিপ্ট তৈরি করতে পারবেন। তবে, বিল্ড স্ক্রিপ্ট কনফিগার করার সময়, আপনার নেটিভ সোর্স ফাইল ও লাইব্রেরির পাথ বিল্ড স্ক্রিপ্টের লোকেশনের সাথে সম্পর্কিত হয়।
- ফাইলের নাম হিসেবে "CMakeLists.txt" লিখুন এবং ঠিক আছে বিকল্পে ক্লিক করুন।
আপনি এখন CMake কমান্ড যোগ করে আপনার বিল্ড স্ক্রিপ্ট কনফিগার করতে পারবেন। নেটিভ সোর্স কোড থেকে নেটিভ লাইব্রেরি তৈরি করার জন্য
CMake-কে নির্দেশ দিতে, আপনার বিল্ড স্ক্রিপ্টে cmake_minimum_required() এবং add_library() কমান্ড যোগ করুন:
# Sets the minimum version of CMake required to build your native library.
# This ensures that a certain set of CMake features is available to
# your build.
cmake_minimum_required(VERSION 3.4.1)
# Specifies a library name, specifies whether the library is STATIC or
# SHARED, and provides relative paths to the source code. You can
# define multiple libraries by adding multiple add_library() commands,
# and CMake builds them for you. When you build your app, Gradle
# automatically packages shared libraries with your APK.
add_library( # Specifies the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp )
পরামর্শ: সোর্স ফাইল থেকে নেটিভ লাইব্রেরি তৈরি করার জন্য আপনি যেভাবে CMake-কে বলতে পারেন, ঠিক একইভাবে আপনি
add_executable() কমান্ড ব্যবহার করে CMake-কে বলতে পারেন যাতে সোর্স ফাইল থেকে
এক্সিকিউটেবল তৈরি করা হয়। তবে, আপনার নেটিভ সোর্স থেকে এক্সিকিউটেবল তৈরি করা ঐচ্ছিক এবং আপনার APK-তে প্যাকেজ করার জন্য নেটিভ লাইব্রেরি তৈরি করা বেশিরভাগ প্রোজেক্টের প্রয়োজনীয়তা পূরণ করে।
আপনি যখন
add_library() ব্যবহার করে আপনার CMake বিল্ড স্ক্রিপ্টে একটি সোর্স ফাইল বা লাইব্রেরি যোগ করেন, তখন আপনার প্রোজেক্ট সিঙ্ক করার পরে Android Studio প্রোজেক্ট ভিউতে সংশ্লিষ্ট হেডার ফাইলগুলিও দেখায়। তবে, কম্পাইল করার সময় CMake যাতে আপনার হেডার ফাইল খুঁজে পায়, তার জন্য
আপনাকে CMake বিল্ড স্ক্রিপ্টে include_directories() কমান্ড যোগ করতে হবে
এবং আপনার হেডারের পাথ উল্লেখ করতে হবে:
add_library(...) # Specifies a path to native header files. include_directories(src/main/cpp/include/)
আপনার লাইব্রেরির ফাইলের নাম দেওয়ার জন্য CMake যে কনভেনশন ব্যবহার করে তা নিচে দেওয়া হল:
liblibrary-name.so
যেমন, আপনি যদি বিল্ড স্ক্রিপ্টে আপনার শেয়ার করা লাইব্রেরির নাম হিসেবে "native-lib" উল্লেখ করেন, তাহলে CMake libnative-lib.so নামের একটি ফাইল তৈরি করে। তবে, আপনার Java বা Kotlin কোডে এই লাইব্রেরি লোড করার সময়, CMake বিল্ড স্ক্রিপ্টে আপনার উল্লেখ করা নামটি ব্যবহার করুন:
Kotlin
companion object { init { System.loadLibrary("native-lib"); } }
জাভা
static { System.loadLibrary("native-lib"); }
মনে রাখবেন: আপনি CMake বিল্ড স্ক্রিপ্টে কোনও লাইব্রেরির নাম পরিবর্তন করলে বা সরিয়ে দিলে, Gradle পরিবর্তন প্রয়োগ করার আগে বা আপনার APK থেকে লাইব্রেরির পুরনো ভার্সন সরিয়ে দেওয়ার আগে আপনাকে প্রোজেক্ট ক্লিন করতে হবে। আপনার প্রোজেক্ট ক্লিন করতে, মেনু বার থেকে বিল্ড > প্রোজেক্ট ক্লিন করুন বিকল্প বেছে নিন।
Android Studio অটোমেটিক সোর্স ফাইল ও হেডার Project প্যানে
cpp গ্রুপে যোগ করে। একাধিক add_library() কমান্ড ব্যবহার করে, আপনি CMake-এর জন্য অতিরিক্ত লাইব্রেরি নির্ধারণ করতে পারেন
যা অন্যান্য সোর্স ফাইল থেকে তৈরি করা যায়।
NDK API যোগ করুন
Android NDK-তে নেটিভ API ও লাইব্রেরির সেট থাকে যা আপনার কাজে লাগতে
পারে। আপনার প্রোজেক্টের CMakeLists.txt স্ক্রিপ্ট ফাইলে NDK লাইব্রেরি অন্তর্ভুক্ত করে আপনি এইসব API-এর যেকোনও একটি ব্যবহার করতে পারবেন।
Android প্ল্যাটফর্মে আগে থেকেই প্রি-বিল্ট NDK লাইব্রেরি আছে, তাই আপনাকে সেগুলি তৈরি করতে বা আপনার APK-তে প্যাকেজ করতে হবে না। NDK লাইব্রেরিগুলি ইতিমধ্যে CMake-এর সার্চ পাথের অংশ, তাই আপনাকে স্থানীয় NDK ইনস্টলেশনে লাইব্রেরির লোকেশন উল্লেখ করতে হবে না—আপনাকে শুধু CMake-কে যে লাইব্রেরি ব্যবহার করতে চান তার নাম দিতে হবে এবং আপনার নিজস্ব নেটিভ লাইব্রেরির সাথে লিঙ্ক করতে হবে।
NDK লাইব্রেরি লোকেট করতে এবং ভেরিয়েবল হিসেবে এর পাথ স্টোর করতে,
আপনার CMake বিল্ড স্ক্রিপ্টে find_library() কমান্ড যোগ করুন। বিল্ড স্ক্রিপ্টের অন্যান্য অংশে NDK লাইব্রেরি উল্লেখ করতে আপনি
এই ভেরিয়েবল ব্যবহার করেন।
নিম্নলিখিত স্যাম্পেল Android-নির্দিষ্ট লগ সাপোর্ট লাইব্রেরি লোকেট করে
এবং log-lib-এ এর পাথ স্টোর করে:
find_library( # Defines the name of the path variable that stores the
# location of the NDK library.
log-lib
# Specifies the name of the NDK library that
# CMake needs to locate.
log )
আপনার নেটিভ লাইব্রেরি যাতে log
লাইব্রেরিতে ফাংশন কল করতে পারে, তার জন্য আপনাকে CMake বিল্ড স্ক্রিপ্টে target_link_libraries() কমান্ড ব্যবহার করে
লাইব্রেরিগুলি লিঙ্ক করতে হবে:
find_library(...)
# Links your native library against one or more other native libraries.
target_link_libraries( # Specifies the target library.
native-lib
# Links the log library to the target library.
${log-lib} )
NDK-তে সোর্স কোড হিসেবে কিছু লাইব্রেরিও অন্তর্ভুক্ত থাকে যা আপনাকে তৈরি করতে হবে
এবং আপনার নেটিভ লাইব্রেরির সাথে লিঙ্ক করতে হবে। আপনার CMake বিল্ড স্ক্রিপ্টে add_library() কমান্ড ব্যবহার করে আপনি সোর্স কোডকে
নেটিভ লাইব্রেরিতে কম্পাইল করতে পারেন। আপনার স্থানীয় NDK লাইব্রেরির পাথ প্রদান করতে, আপনি
ANDROID_NDK পাথ ভেরিয়েবল ব্যবহার করতে পারেন, যা Android Studio অটোমেটিক
আপনার জন্য নির্ধারণ করে।
নিম্নলিখিত কমান্ড CMake-কে
android_native_app_glue.c তৈরি করতে বলে, যা NativeActivity
লাইফসাইকেল ইভেন্ট এবং টাচ করে ইনপুট দেওয়ার পদ্ধতি, একটি স্ট্যাটিক লাইব্রেরিতে ম্যানেজ করে এবং এটিকে
native-lib-এর সাথে লিঙ্ক করে:
add_library( app-glue
STATIC
${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c )
# You need to link static libraries against your shared native library.
target_link_libraries( native-lib app-glue ${log-lib} )
অন্যান্য আগে থেকে তৈরি লাইব্রেরি যোগ করুন
আগে থেকে তৈরি লাইব্রেরি যোগ করা CMake-এর জন্য অন্য নেটিভ লাইব্রেরি নির্দিষ্ট করার মতোই
তৈরি করা। তবে, লাইব্রেরিটি আগে থেকেই তৈরি করা আছে বলে, CMake-কে জানাতে আপনাকে
IMPORTED ফ্ল্যাগ ব্যবহার করতে হবে যে আপনি
শুধুমাত্র আপনার প্রোজেক্টে লাইব্রেরিটি ইমপোর্ট করতে চান:
add_library( imported-lib
SHARED
IMPORTED )
তারপর আপনাকে
set_target_properties() কমান্ড ব্যবহার করে লাইব্রেরির পাথ উল্লেখ করতে হবে, যেমন
নিচে দেখানো হয়েছে।
কিছু লাইব্রেরি নির্দিষ্ট CPU আর্কিটেকচার বা
অ্যাপ্লিকেশন বাইনারি ইন্টারফেস (ABI)-এর জন্য আলাদা প্যাকেজ প্রদান করে এবং
সেগুলিকে আলাদা ডিরেক্টরিতে সাজায়। এই পদ্ধতি লাইব্রেরিগুলিকে নির্দিষ্ট CPU আর্কিটেকচারের সুবিধা নিতে সাহায্য করে এবং আপনাকে শুধুমাত্র আপনার পছন্দের লাইব্রেরির ভার্সন ব্যবহার করার অনুমতি দেয়। আপনার CMake বিল্ড স্ক্রিপ্টে কোনও লাইব্রেরির একাধিক ABI ভার্সন যোগ করতে, লাইব্রেরির প্রতিটি ভার্সনের জন্য একাধিক কমান্ড না লিখে, আপনি ANDROID_ABI পাথ ভেরিয়েবল ব্যবহার করতে পারেন। এই ভেরিয়েবলটি ডিফল্ট NDK-এর সাথে কাজ করে এমন ABI-এর তালিকা অথবা আপনি
ম্যানুয়ালি Gradle কনফিগার করে ব্যবহার করেন এমন ABI-এর ফিল্টার করা তালিকা
ব্যবহার করে। যেমন:
add_library(...)
set_target_properties( # Specifies the target library.
imported-lib
# Specifies the parameter you want to define.
PROPERTIES IMPORTED_LOCATION
# Provides the path to the library you want to import.
imported-lib/src/${ANDROID_ABI}/libimported-lib.so )
কম্পাইল করার সময় CMake যাতে আপনার হেডার ফাইল খুঁজে পায়, তার জন্য আপনাকে
include_directories() কমান্ড ব্যবহার করতে হবে এবং আপনার হেডার ফাইলের
পাথ অন্তর্ভুক্ত করতে হবে:
include_directories( imported-lib/include/ )
মনে রাখবেন: আপনি যদি এমন একটি প্রি-বিল্ট লাইব্রেরি প্যাকেজ করতে চান যা
বিল্ড-টাইম ডিপেন্ডেন্সি নয়—যেমন, imported-lib-এর ডিপেন্ডেন্সি হিসেবে কাজ করে এমন একটি প্রি-বিল্ট লাইব্রেরি যোগ করার সময়, লাইব্রেরি লিঙ্ক করার জন্য আপনাকে নিম্নলিখিত নির্দেশাবলী
অনুসরণ করতে হবে না।
আপনার নিজস্ব নেটিভ লাইব্রেরিতে প্রি-বিল্ট লাইব্রেরি লিঙ্ক করতে, আপনার CMake বিল্ড স্ক্রিপ্টে
target_link_libraries() কমান্ডে এটি যোগ করুন:
target_link_libraries( native-lib imported-lib app-glue ${log-lib} )
আপনার APK-তে প্রি-বিল্ট লাইব্রেরি প্যাকেজ করতে, আপনাকে
ম্যানুয়ালি Gradle কনফিগার করতে হবে, যেখানে sourceSets ব্লক থাকবে, যাতে
আপনার .so ফাইলের পাথ অন্তর্ভুক্ত করা যায়। APK তৈরি করার পরে, APK Analyzer ব্যবহার করে আপনি যাচাই করতে পারবেন যে কোন লাইব্রেরি Gradle আপনার APK-তে প্যাকেজ করে।
অন্যান্য CMake প্রোজেক্ট অন্তর্ভুক্ত করুন
আপনি একাধিক CMake প্রোজেক্ট তৈরি করতে এবং আপনার Android প্রোজেক্টে সেগুলির আউটপুট অন্তর্ভুক্ত করতে চাইলে, আপনি টপ-লেভেল CMake বিল্ড স্ক্রিপ্ট (যেটি আপনি
Gradle-এর সাথে
লিঙ্ক করেন) হিসেবে একটি CMakeLists.txt ফাইল ব্যবহার করতে পারেন এবং সেই বিল্ড স্ক্রিপ্টের ডিপেন্ডেন্সি হিসেবে অতিরিক্ত CMake প্রোজেক্ট যোগ করতে পারেন। নিম্নলিখিত টপ-লেভেল CMake বিল্ড স্ক্রিপ্ট
add_subdirectory() কমান্ড ব্যবহার করে
অন্য একটি CMakeLists.txt ফাইলকে বিল্ড ডিপেন্ডেন্সি হিসেবে নির্দিষ্ট করে এবং তারপরে
এর আউটপুটের সাথে লিঙ্ক করে, ঠিক যেমন এটি অন্য কোনও প্রি-বিল্ড লাইব্রেরির সাথে করে।
# Sets lib_src_DIR to the path of the target CMake project.
set( lib_src_DIR ../gmath )
# Sets lib_build_DIR to the path of the desired output directory.
set( lib_build_DIR ../gmath/outputs )
file(MAKE_DIRECTORY ${lib_build_DIR})
# Adds the CMakeLists.txt file located in the specified directory
# as a build dependency.
add_subdirectory( # Specifies the directory of the CMakeLists.txt file.
${lib_src_DIR}
# Specifies the directory for the build outputs.
${lib_build_DIR} )
# Adds the output of the additional CMake build as a prebuilt static
# library and names it lib_gmath.
add_library( lib_gmath STATIC IMPORTED )
set_target_properties( lib_gmath PROPERTIES IMPORTED_LOCATION
${lib_build_DIR}/${ANDROID_ABI}/lib_gmath.a )
include_directories( ${lib_src_DIR}/include )
# Links the top-level CMake build output against lib_gmath.
target_link_libraries( native-lib ... lib_gmath )
কমান্ড লাইন থেকে CMake কল করুন
Android Studio-র বাইরে Ninja প্রোজেক্ট তৈরি করার জন্য CMake-কে কল করতে নিম্নলিখিত কমান্ড ব্যবহার করুন:
cmake
-Hpath/to/cmakelists/folder
-Bpath/to/generated/ninja/project/debug/ABI
-DANDROID_ABI=ABI // For example, arm64-v8a
-DANDROID_PLATFORM=platform-version-string // For example, android-16
-DANDROID_NDK=android-sdk/ndk/ndk-version
-DCMAKE_TOOLCHAIN_FILE=android-sdk/ndk/ndk-version/build/cmake/android.toolchain.cmake
-G Ninja
এই কমান্ড Ninja প্রোজেক্ট তৈরি করবে যা Android এক্সিকিউটেবল লাইব্রেরি (.so ফাইল) তৈরি করার জন্য এক্সিকিউট করা যেতে পারে। NDK-এর CMake সাপোর্ট ব্যবহার করার জন্য
CMAKE_TOOLCHAIN_FILE প্রয়োজন। CMake 3.21 বা তার পরের ভার্সনের জন্য, CMake-এর বিল্ট-ইন
NDK সাপোর্ট ব্যবহার করা যেতে পারে, তবে CMake-এর Android-এর জন্য ক্রস কম্পাইলিং ডকুমেন্টেশনে
যেমন বর্ণনা করা হয়েছে, ভেরিয়েবলের একটি ভিন্ন গ্রুপ ব্যবহার করতে হবে।