CMake কনফিগার করুন

একটি CMake বিল্ড স্ক্রিপ্ট হল একটি প্লেইন টেক্সট ফাইল যা আপনাকে অবশ্যই CMakeLists.txt নাম দিতে হবে এবং আপনার C/C++ লাইব্রেরিগুলি তৈরি করতে CMake ব্যবহার করে কমান্ডগুলি অন্তর্ভুক্ত করে। যদি আপনার নেটিভ সোর্সগুলিতে ইতিমধ্যেই একটি CMake বিল্ড স্ক্রিপ্ট না থাকে, তাহলে আপনাকে নিজেই একটি তৈরি করতে হবে এবং উপযুক্ত CMake কমান্ডগুলি অন্তর্ভুক্ত করতে হবে। কিভাবে CMake ইনস্টল করতে হয় তা জানতে, NDK এবং CMake ইনস্টল এবং কনফিগার দেখুন।

আপনার নেটিভ লাইব্রেরি তৈরি করার সময় CMake কে কোন উৎসগুলি ব্যবহার করতে হবে তা জানাতে আপনার বিল্ড স্ক্রিপ্টে আপনার অন্তর্ভুক্ত করা উচিত এমন কিছু মৌলিক কমান্ড এই বিভাগে অন্তর্ভুক্ত করে। আরও জানতে, CMake কমান্ড সম্পর্কে অফিসিয়াল ডকুমেন্টেশন পড়ুন।

আপনি একটি নতুন CMake বিল্ড স্ক্রিপ্ট কনফিগার করার পরে, আপনাকে আপনার CMake প্রকল্পকে বিল্ড নির্ভরতা হিসাবে অন্তর্ভুক্ত করতে Gradle কনফিগার করতে হবে, যাতে Gradle আপনার অ্যাপের APK দিয়ে আপনার নেটিভ লাইব্রেরি তৈরি এবং প্যাকেজ করে।

দ্রষ্টব্য: যদি আপনার প্রকল্প ndk-build ব্যবহার করে, তাহলে আপনাকে CMake বিল্ড স্ক্রিপ্ট তৈরি করতে হবে না। আপনি আপনার Android.mk ফাইলে একটি পথ প্রদান করে আপনার বিদ্যমান নেটিভ লাইব্রেরি প্রজেক্টকে অন্তর্ভুক্ত করতে Gradle কনফিগার করতে পারেন।

একটি CMake বিল্ড স্ক্রিপ্ট তৈরি করুন

একটি প্লেইন টেক্সট ফাইল তৈরি করতে যা আপনি আপনার CMake বিল্ড স্ক্রিপ্ট হিসাবে ব্যবহার করতে পারেন, নিম্নরূপ এগিয়ে যান:

  1. IDE এর বাম দিক থেকে প্রজেক্ট প্যানটি খুলুন এবং ড্রপ-ডাউন মেনু থেকে প্রজেক্ট ভিউ নির্বাচন করুন।
  2. your-module রুট ডিরেক্টরিতে ডান-ক্লিক করুন এবং নতুন > ফাইল নির্বাচন করুন।

    দ্রষ্টব্য: আপনি যে কোনো স্থানে বিল্ড স্ক্রিপ্ট তৈরি করতে পারেন। যাইহোক, বিল্ড স্ক্রিপ্ট কনফিগার করার সময়, আপনার নেটিভ সোর্স ফাইল এবং লাইব্রেরির পাথগুলি বিল্ড স্ক্রিপ্টের অবস্থানের সাথে সম্পর্কিত।

  3. ফাইলের নাম হিসাবে "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 স্টুডিও প্রকল্প ভিউতে সংশ্লিষ্ট হেডার ফাইলগুলিও দেখায়। যাইহোক, কম্পাইলের সময় CMake আপনার হেডার ফাইলগুলি সনাক্ত করার জন্য, আপনাকে আপনার CMake বিল্ড স্ক্রিপ্টে include_directories() কমান্ড যোগ করতে হবে এবং আপনার হেডারগুলির পথ নির্দিষ্ট করতে হবে:

add_library(...)

# Specifies a path to native header files.
include_directories(src/main/cpp/include/)

আপনার লাইব্রেরির ফাইলের নাম দেওয়ার জন্য CMake যে কনভেনশনটি ব্যবহার করে তা নিম্নরূপ:

lib library-name .so

উদাহরণস্বরূপ, আপনি যদি বিল্ড স্ক্রিপ্টে আপনার ভাগ করা লাইব্রেরির নাম হিসাবে "native-lib" নির্দিষ্ট করেন, CMake libnative-lib.so নামে একটি ফাইল তৈরি করে। যাইহোক, আপনার জাভা বা কোটলিন কোডে এই লাইব্রেরিটি লোড করার সময়, CMake বিল্ড স্ক্রিপ্টে আপনার নির্দিষ্ট করা নামটি ব্যবহার করুন:

কোটলিন

companion object {
    init {
        System.loadLibrary("native-lib");
    }
}

জাভা

static {
    System.loadLibrary("native-lib");
}

দ্রষ্টব্য: আপনি যদি আপনার CMake বিল্ড স্ক্রিপ্টে একটি লাইব্রেরির নাম পরিবর্তন করেন বা সরিয়ে দেন, তাহলে Gradle পরিবর্তনগুলি প্রয়োগ করার আগে বা আপনার APK থেকে লাইব্রেরির পুরানো সংস্করণটি সরিয়ে দেওয়ার আগে আপনাকে আপনার প্রকল্পটি পরিষ্কার করতে হবে। আপনার প্রকল্প পরিষ্কার করতে, মেনু বার থেকে বিল্ড > ক্লিন প্রজেক্ট নির্বাচন করুন।

অ্যান্ড্রয়েড স্টুডিও স্বয়ংক্রিয়ভাবে প্রোজেক্ট ফলকে cpp গ্রুপে সোর্স ফাইল এবং হেডার যোগ করে। একাধিক add_library() কমান্ড ব্যবহার করে, আপনি CMake-এর জন্য অন্যান্য সোর্স ফাইল থেকে তৈরি করার জন্য অতিরিক্ত লাইব্রেরি সংজ্ঞায়িত করতে পারেন।

NDK API যোগ করুন

অ্যান্ড্রয়েড এনডিকে নেটিভ এপিআই এবং লাইব্রেরিগুলির একটি সেট সরবরাহ করে যা আপনার কাজে লাগতে পারে। আপনি আপনার প্রকল্পের CMakeLists.txt স্ক্রিপ্ট ফাইলে NDK লাইব্রেরিগুলি অন্তর্ভুক্ত করে এই APIগুলির যেকোনো একটি ব্যবহার করতে পারেন।

প্রি-বিল্ট NDK লাইব্রেরিগুলি ইতিমধ্যেই Android প্ল্যাটফর্মে বিদ্যমান, তাই আপনাকে সেগুলি তৈরি করতে বা আপনার APK এ প্যাকেজ করার দরকার নেই৷ যেহেতু NDK লাইব্রেরিগুলি ইতিমধ্যেই CMake-এর অনুসন্ধান পথের একটি অংশ, তাই আপনাকে আপনার স্থানীয় NDK ইনস্টলেশনে লাইব্রেরির অবস্থান নির্দিষ্ট করতে হবে না-আপনাকে শুধুমাত্র CMake-কে আপনি যে লাইব্রেরিটি ব্যবহার করতে চান তার নাম দিতে হবে এবং লিঙ্ক করতে হবে। এটা আপনার নিজের নেটিভ লাইব্রেরির বিরুদ্ধে।

একটি NDK লাইব্রেরি সনাক্ত করতে এবং একটি পরিবর্তনশীল হিসাবে এর পথ সংরক্ষণ করতে আপনার CMake বিল্ড স্ক্রিপ্টে find_library() কমান্ডটি যোগ করুন। আপনি বিল্ড স্ক্রিপ্টের অন্যান্য অংশে NDK লাইব্রেরি উল্লেখ করতে এই ভেরিয়েবলটি ব্যবহার করেন। নিম্নলিখিত নমুনাটি অ্যান্ড্রয়েড-নির্দিষ্ট লগ সমর্থন লাইব্রেরি সনাক্ত করে এবং 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 স্টুডিও আপনার জন্য স্বয়ংক্রিয়ভাবে সংজ্ঞায়িত করে।

নিম্নলিখিত কমান্ডটি 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 নির্মাণের জন্য অন্য একটি নেটিভ লাইব্রেরি নির্দিষ্ট করার অনুরূপ। যাইহোক, যেহেতু লাইব্রেরিটি ইতিমধ্যেই তৈরি করা হয়েছে, তাই আপনাকে সিমেকে বলতে IMPORTED পতাকা ব্যবহার করতে হবে যে আপনি শুধুমাত্র আপনার প্রকল্পে লাইব্রেরি আমদানি করতে চান:

add_library( imported-lib
             SHARED
             IMPORTED )

তারপর আপনাকে নীচে দেখানো হিসাবে set_target_properties() কমান্ড ব্যবহার করে লাইব্রেরির পথ নির্দিষ্ট করতে হবে।

কিছু লাইব্রেরি নির্দিষ্ট CPU আর্কিটেকচার বা অ্যাপ্লিকেশন বাইনারি ইন্টারফেস (ABI) এর জন্য আলাদা প্যাকেজ প্রদান করে এবং সেগুলিকে আলাদা ডিরেক্টরিতে সংগঠিত করে। এই পদ্ধতিটি লাইব্রেরিগুলিকে নির্দিষ্ট সিপিইউ আর্কিটেকচারের সুবিধা নিতে সাহায্য করে যখন আপনাকে আপনার পছন্দের লাইব্রেরির সংস্করণগুলি ব্যবহার করার অনুমতি দেয়। আপনার CMake বিল্ড স্ক্রিপ্টে একটি লাইব্রেরির একাধিক ABI সংস্করণ যোগ করতে, লাইব্রেরির প্রতিটি সংস্করণের জন্য একাধিক কমান্ড না লিখে, আপনি ANDROID_ABI পাথ ভেরিয়েবল ব্যবহার করতে পারেন। এই ভেরিয়েবলটি ডিফল্ট ABI গুলির একটি তালিকা ব্যবহার করে যা NDK সমর্থন করে , অথবা ABI গুলির একটি ফিল্টার করা তালিকা যা আপনি ম্যানুয়ালি ব্যবহার করার জন্য Gradle কনফিগার করেন । উদাহরণ স্বরূপ:

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-এ প্রি-বিল্ট লাইব্রেরি প্যাকেজ করতে, আপনার .so ফাইলের পাথ অন্তর্ভুক্ত করার জন্য আপনাকে sourceSets ব্লকের সাথে ম্যানুয়ালি গ্রেডল কনফিগার করতে হবে। আপনার APK তৈরি করার পরে, আপনি APK বিশ্লেষক ব্যবহার করে আপনার APK এ কোন লাইব্রেরি গ্রেডল প্যাকেজগুলি যাচাই করতে পারেন।

অন্যান্য CMake প্রকল্প অন্তর্ভুক্ত করুন

আপনি যদি একাধিক CMake প্রজেক্ট তৈরি করতে চান এবং আপনার অ্যান্ড্রয়েড প্রোজেক্টে তাদের আউটপুট অন্তর্ভুক্ত করতে চান, তাহলে আপনি একটি CMakeLists.txt ফাইলকে উচ্চ-স্তরের CMake বিল্ড স্ক্রিপ্ট হিসেবে ব্যবহার করতে পারেন (যেটি আপনি Gradle-এর সাথে লিঙ্ক করেন ) এবং নির্ভরতা হিসেবে অতিরিক্ত CMake প্রজেক্ট যোগ করতে পারেন। যে বিল্ড স্ক্রিপ্ট. নিম্নলিখিত শীর্ষ-স্তরের CMake বিল্ড স্ক্রিপ্টটি একটি বিল্ড নির্ভরতা হিসাবে অন্য CMakeLists.txt ফাইলকে নির্দিষ্ট করতে add_subdirectory() কমান্ড ব্যবহার করে এবং তারপর এটির আউটপুটের সাথে লিঙ্ক করে ঠিক যেমন এটি অন্য কোনো পূর্বনির্মাণ লাইব্রেরির সাথে।

# 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 কল করুন

অ্যান্ড্রয়েড স্টুডিওর বাইরে একটি নিনজা প্রকল্প তৈরি করতে 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

এই কমান্ডটি নিনজা প্রজেক্ট তৈরি করবে যা অ্যান্ড্রয়েড এক্সিকিউটেবল লাইব্রেরি ( .so ফাইল) তৈরি করতে কার্যকর করা যেতে পারে। NDK-এর CMake সমর্থন ব্যবহার করার জন্য CMAKE_TOOLCHAIN_FILE প্রয়োজন৷ CMake 3.21 বা তার পরের জন্য, CMake-এর অন্তর্নির্মিত NDK সমর্থন পরিবর্তে ব্যবহার করা যেতে পারে, তবে Android ডকুমেন্টেশনের জন্য CMake এর ক্রস কম্পাইলিং -এ বর্ণিত ভেরিয়েবলের একটি ভিন্ন গ্রুপ ব্যবহার করা আবশ্যক।