Android.mk

توضّح هذه الصفحة بنية ملف الإصدار Android.mk الذي يستخدمه ndk-build.

نظرة عامة

يوجد ملف Android.mk في دليل فرعي ضمن دليل jni/ لمشروعك، ويصف المصادر والمكتبات المشتركة لنظام الإصدار. إنه في الحقيقة جزء صغير من ملف إنشاء GNU يحلّله نظام الإنشاء مرة واحدة أو أكثر. يُعد ملف Android.mk مفيدًا لتحديد الإعدادات على مستوى المشروع التي يتركها Application.mk ونظام الإنشاء ومتغيرات البيئة غير محددة. ويمكنه أيضًا إلغاء الإعدادات على مستوى المشروع لوحدات معيّنة.

تسمح لك بنية Android.mk بتجميع المصادر في وحدات. الوحدة عبارة عن مكتبة ثابتة أو مكتبة مشتركة أو وحدة تنفيذية مستقلة. يمكنك تحديد وحدة واحدة أو أكثر في كل ملف Android.mk ويمكنك استخدام الملف المصدر نفسه في وحدات متعددة. يضع نظام الإصدار المكتبات المشتركة فقط في حزمة التطبيق الخاصة بك. بالإضافة إلى ذلك، يمكن للمكتبات الثابتة إنشاء مكتبات مشتركة.

بالإضافة إلى مكتبات التغليف، يعالج نظام الإنشاء مجموعة متنوعة من التفاصيل الأخرى من أجلك. على سبيل المثال، لن تحتاج إلى إدراج ملفات العنوان أو تبعيات صريحة بين الملفات التي تم إنشاؤها في ملف Android.mk. يحسب نظام إنشاء NDK هذه العلاقات تلقائيًا نيابة عنك. ونتيجةً لذلك، من المفترض أن يكون بإمكانك الاستفادة من الدعم الجديد الخاص بسلسلة الأدوات/النظام الأساسي في إصدارات NDK المستقبلية بدون الحاجة إلى النقر على ملف Android.mk.

بنية هذا الملف قريبة جدًا من البنية المستخدَمة في ملفات Android.mk التي يتم توزيعها مع مشروع Android المفتوح المصدر الكامل. في حين أنّ تنفيذ نظام الإنشاء الذي يستخدمهما يختلف عن غيره، فإن التشابه بينها هو قرار تصميم متعمّد يهدف إلى تسهيل عملية إعادة استخدام رمز المصدر للمكتبات الخارجية.

الأساسيات

قبل استكشاف البنية بالتفصيل، من المفيد البدء بفهم أساسيات ما يحتويه ملف Android.mk. يستخدم هذا القسم ملف Android.mk في نموذج Hello-JNI لتحقيق هذه الغاية، ويوضّح الدور الذي يؤديه كل سطر في الملف.

يجب أن يبدأ ملف Android.mk بتعريف المتغيّر LOCAL_PATH:

LOCAL_PATH := $(call my-dir)

يشير هذا المتغير إلى موقع ملفات المصدر في شجرة التطوير. هنا، تعرض دالة الماكرو my-dir، التي يوفّرها نظام الإصدار، مسار الدليل الحالي (الدليل الذي يحتوي على ملف Android.mk نفسه).

يعلن السطر التالي عن المتغيّر CLEAR_VARS الذي يوفّره نظام الإنشاء.

include $(CLEAR_VARS)

يشير المتغيّر CLEAR_VARS إلى ملف GNU Makefile خاص يمحو العديد من متغيّرات LOCAL_XXX، مثل LOCAL_MODULE وLOCAL_SRC_FILES وLOCAL_STATIC_LIBRARIES. يُرجى العلم أنّه لا يتم محو LOCAL_PATH. يجب أن يحتفظ هذا المتغير بقيمته لأن النظام يحلل جميع ملفات التحكم في الإصدار في سياق تنفيذ GNU واحد يكون فيه جميع المتغيرات عمومية. يجب عليك (إعادة) تعريف هذا المتغير قبل وصف كل وحدة.

بعد ذلك، يُخزّن المتغيّر LOCAL_MODULE اسم الوحدة التي تريد إنشاءها. استخدِم هذا المتغيّر مرة واحدة لكل وحدة في تطبيقك.

LOCAL_MODULE := hello-jni

يجب أن يكون اسم كل وحدة فريدًا ولا يحتوي على أي مسافات. عندما ينشئ نظام الإصدار الملف النهائي للمكتبة المشتركة، فإنّه يضيف تلقائيًا البادئة واللاحقة المناسبتَين إلى الاسم الذي تحدّده للسمة LOCAL_MODULE. على سبيل المثال، يؤدي المثال الذي يظهر أعلاه إلى إنشاء مكتبة تسمى libhello-jni.so.

يعدد السطر التالي الملفات المصدر، مع مسافات تحدد عدة ملفات:

LOCAL_SRC_FILES := hello-jni.c

يجب أن يحتوي المتغيّر LOCAL_SRC_FILES على قائمة بملفات المصدر C و/أو C++ لدمجها في وحدة.

يساعد السطر الأخير النظام في ربط كل شيء معًا:

include $(BUILD_SHARED_LIBRARY)

يشير المتغيّر BUILD_SHARED_LIBRARY إلى نص برمجي GNU Makefile يجمع كل المعلومات التي حدّدتها في متغيّرات LOCAL_XXX منذ آخر include. يحدد هذا النص ما يجب إنشاؤه، وكيفية القيام بذلك.

هناك أمثلة أكثر تعقيدًا في نماذج الأدلة، مع ملفات Android.mk المعلَّقة التي يمكنك الاطّلاع عليها. بالإضافة إلى ذلك، يقدّم القسم عيّنة: النشاط الأصلي شرحًا تفصيليًا لملف Android.mk الخاص بهذا النموذج. أخيرًا، توفِّر المتغيرات ووحدات الماكرو مزيدًا من المعلومات عن المتغيرات من هذا القسم.

المتغيرات ووحدات الماكرو

يوفّر نظام الإصدار العديد من المتغيّرات المحتمَلة لاستخدامها في ملف Android.mk. تأتي العديد من هذه المتغيرات مع قيم محددة مسبقًا. غير ذلك، يمكنك تعيين.

بالإضافة إلى هذه المتغيرات، يمكنك أيضًا تحديد المتغيّرات العشوائية لديك. إذا قمت بذلك، فضع في اعتبارك أن نظام إنشاء NDK يحتفظ بأسماء المتغيرات التالية:

  • الأسماء التي تبدأ بـ LOCAL_، مثل LOCAL_MODULE
  • الأسماء التي تبدأ بـ PRIVATE_ أو NDK_ أو APP يستخدم نظام الإنشاء هذه الإعدادات داخليًا.
  • الأسماء الصغيرة، مثل my-dir. يستخدم نظام الإنشاء هذه العناصر داخليًا أيضًا.

إذا كنت بحاجة إلى تحديد المتغيّرات المناسبة لك في ملف Android.mk، ننصحك بإضافة السمة MY_ في بداية أسمائها.

المتغيرات التي تم تحديدها من خلال NDK

يناقش هذا القسم متغيرات GNU Make التي يحددها نظام الإصدار، قبل تحليل ملف Android.mk. في ظروف معيّنة، قد يحلل NDK ملف Android.mk عدة مرات، ويستخدم تعريفًا مختلفًا لبعض هذه المتغيّرات في كل مرة.

محو_VARS

يشير هذا المتغيّر إلى نص برمجي للإصدار لا يحدِّد جميع متغيرات LOCAL_XXX المذكورة تقريبًا في قسم "المتغيّرات التي حدّدها المطوّر" أدناه. استخدم هذا المتغير لتضمين هذا البرنامج النصي قبل وصف وحدة جديدة. بناء الجملة لاستخدامه هو:

include $(CLEAR_VARS)

BUILD_EXECUTABLE

يشير هذا المتغيّر إلى نص برمجي للإصدار يجمع كل المعلومات عن الوحدة التي قدّمتها في متغيّرات LOCAL_XXX، ويحدّد كيفية إنشاء هدف قابل للتنفيذ من المصادر التي أدرجتها. يُرجى العلم أنّ استخدام هذا النص البرمجي يتطلّب أن تكون قد سبق لك تخصيص قيم للسمتَين LOCAL_MODULE وLOCAL_SRC_FILES على الأقل (لمزيد من المعلومات عن هذين المتغيّرات، يُرجى الاطّلاع على متغيّرات وصف الوحدة).

بناء الجملة لاستخدام هذا المتغير هو:

include $(BUILD_EXECUTABLE)

بناء

يشير هذا المتغيّر إلى نص برمجي للإصدار يجمع كل المعلومات عن الوحدة التي قدّمتها في متغيّرات LOCAL_XXX، ويحدّد كيفية إنشاء مكتبة مشتركة مستهدفة من المصادر التي أدرجتها. يُرجى العلم أنّ استخدام هذا النص البرمجي يتطلّب أن تكون قد سبق لك تخصيص قيم للسمتَين LOCAL_MODULE وLOCAL_SRC_FILES على الأقل (لمزيد من المعلومات عن هذين المتغيّرات، يُرجى الاطّلاع على متغيّرات وصف الوحدة).

بناء الجملة لاستخدام هذا المتغير هو:

include $(BUILD_SHARED_LIBRARY)

يؤدي متغيّر المكتبة المشتركة إلى إنشاء نظام الإصدار لملف مكتبة بالامتداد .so.

إنشاء_مكتب_الحالة

يتم استخدام أحد خيارات BUILD_SHARED_LIBRARY لإنشاء مكتبة ثابتة. لا ينسخ نظام الإنشاء المكتبات الثابتة إلى مشروعك/حِزمك، ولكن يمكنه استخدامها لإنشاء مكتبات مشتركة (راجِع LOCAL_STATIC_LIBRARIES وLOCAL_WHOLE_STATIC_LIBRARIES أدناه). بناء الجملة لاستخدام هذا المتغير هو:

include $(BUILD_STATIC_LIBRARY)

يؤدي متغيّر المكتبة الثابتة إلى إنشاء نظام الإصدار لمكتبة تتضمّن إضافة .a.

PREBUILT_SHARED_LIBRARY

تشير هذه السمة إلى نص برمجي للإصدار يُستخدَم لتحديد مكتبة مشترَكة تم إنشاؤها مسبقًا. وعلى عكس حالة BUILD_SHARED_LIBRARY وBUILD_STATIC_LIBRARY، لا يمكن أن تكون قيمة LOCAL_SRC_FILES هنا ملفًا مصدرًا. بدلاً من ذلك، يجب أن يكون مسارًا واحدًا لمكتبة مشتركة تم إنشاؤها مسبقًا، مثل foo/libfoo.so. بناء الجملة لاستخدام هذا المتغير هو:

include $(PREBUILT_SHARED_LIBRARY)

يمكنك أيضًا الإشارة إلى مكتبة معدّة مسبقًا في وحدة أخرى باستخدام المتغيّر LOCAL_PREBUILTS. لمزيد من المعلومات حول استخدام المكتبات مسبقة الإنشاء، يمكنك الاطّلاع على استخدام المكتبات مسبقة الإنشاء.

PREBUILT_StatIC_LIBRARY

الطريقة نفسها مثل PREBUILT_SHARED_LIBRARY، ولكن بالنسبة إلى مكتبة ثابتة مُنشأة مسبقًا. لمزيد من المعلومات حول استخدام المكتبات مسبقة الإنشاء، يمكنك الاطّلاع على استخدام المكتبات مسبقة الإنشاء.

متغيرات المعلومات المستهدفة

يحلّل نظام الإصدار Android.mk مرة واحدة لكل واجهة تطبيق ثنائية (ABI) يتم تحديدها من خلال المتغيّر APP_ABI، والذي يتم تحديده عادةً في ملف Application.mk. إذا كانت قيمة APP_ABI هي all، يحلّل نظام الإنشاء Android.mk مرة واحدة لكل واجهة ABI متوافقة مع NDK. يصف هذا القسم المتغيّرات التي يحدّدها نظام الإصدار في كل مرة يحلّل فيها Android.mk.

القوس المستهدف

مجموعة وحدة المعالجة المركزية (CPU) التي يستهدفها نظام الإصدار أثناء تحليل ملف Android.mk هذا. سيكون هذا المتغيّر واحدًا مما يلي: arm أو arm64 أو x86 أو x86_64.

النظام الأساسي المستهدف

رقم مستوى واجهة برمجة تطبيقات Android الذي يستهدفه نظام الإصدار أثناء تحليله لملف Android.mk هذا. على سبيل المثال، تتوافق صور نظام Android 5.1 مع المستوى 22 من واجهة برمجة تطبيقات Android: android-22. للحصول على قائمة كاملة بأسماء الأنظمة الأساسية وصور نظام Android المقابلة، يمكنك الاطّلاع على واجهات برمجة التطبيقات الأصلية. يوضح المثال التالي بناء الجملة لاستخدام هذا المتغير:

ifeq ($(TARGET_PLATFORM),android-22)
    # ... do something ...
endif

TARGET_ARCH_ABI

يشير ذلك المصطلح إلى واجهة التطبيق الثنائية (ABI) التي يستهدفها نظام الإصدار أثناء تحليل ملف Android.mk هذا. يعرض الجدول 1 إعدادات ABI المستخدَمة لكل وحدة معالجة مركزية وبنية متوافقة.

الجدول 1. إعدادات ABI لوحدات المعالجة المركزية (CPU) والبُنى الأساسية المختلفة

وحدة المعالجة المركزية (CPU) والبنية الأساسية الإعدادات
الإصدار 7 من ARM armeabi-v7a
ARMv8 AArch64 arm64-v8a
i686 x86
x86-64 x86_64

يوضّح المثال التالي كيفية التحقّق من ARMv8 AArch64 كمجموعة مستهدَفة من وحدة المعالجة المركزية (CPU) وواجهة ABI:

ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
  # ... do something ...
endif

لمزيد من التفاصيل حول واجهات ABI للبنية ومشاكل التوافق المرتبطة بها، يُرجى الرجوع إلى واجهات ABI في Android.

ستكون واجهات ABI المستهدفة الجديدة في المستقبل لها قيم مختلفة.

واجهة برمجة التطبيقات المستهدفة

سلسلة من مستوى واجهة برمجة تطبيقات Android المستهدَف وABI وهي مفيدة بشكل خاص عندما تريد إجراء الاختبار على صورة نظام مستهدَف محددة لجهاز حقيقي. على سبيل المثال، للتحقّق من توفُّر جهاز ARM 64 بت يعمل بالمستوى 22 من واجهة برمجة تطبيقات Android:

ifeq ($(TARGET_ABI),android-22-arm64-v8a)
  # ... do something ...
endif

متغيرات وصف الوحدة

تصف المتغيرات في هذا القسم الوحدة الخاصة بنظام التشغيل. يجب أن يتبع كل وصف للوحدة التدفق الأساسي التالي:

  1. يجب إعداد المتغيرات المرتبطة بالوحدة أو إلغاء تحديدها باستخدام المتغيّر CLEAR_VARS.
  2. تعيين القيم للمتغيرات المستخدمة لوصف الوحدة.
  3. اضبط نظام الإصدار NDK على استخدام النص البرمجي للإصدار المناسب للوحدة النمطية، باستخدام المتغيّر BUILD_XXX.

المسار_المحلي

ويُستخدم هذا المتغير في تحديد مسار الملف الحالي. عليك تحديده في بداية ملف Android.mk. ويوضح المثال التالي كيفية القيام بذلك:

LOCAL_PATH := $(call my-dir)

لا يؤدّي النص البرمجي الذي يتضمّن CLEAR_VARS نقطة إلى محو هذا المتغيّر. وبالتالي، ما عليك سوى تحديده مرة واحدة، حتى إذا كان ملف Android.mk يصف وحدات متعددة.

الوحدة_المحلية

يخزن هذا المتغير اسم الوحدة. ويجب أن يكون فريدًا بين جميع أسماء الوحدات ولا يحتوي على أي مسافات. ويجب تحديدها قبل تضمين أي نصوص برمجية (بخلاف تلك الخاصة بـ CLEAR_VARS). ولا تحتاج إلى إضافة البادئة lib أو امتداد الملف .so أو .a، لأنّ نظام الإصدار يُجري هذه التعديلات تلقائيًا. في ملفَي Android.mk وApplication.mk، يمكنك الإشارة إلى الوحدة باستخدام اسمها غير المعدّل. على سبيل المثال، يؤدي السطر التالي إلى إنشاء وحدة مكتبة مشتركة تسمى libfoo.so:

LOCAL_MODULE := "foo"

إذا أردت أن يكون للوحدة التي تم إنشاؤها اسمًا غير lib + قيمة LOCAL_MODULE، يمكنك استخدام المتغيّر LOCAL_MODULE_FILENAME لإعطاء الوحدة التي تم إنشاؤها اسمًا من اختيارك بدلاً من ذلك.

LOCAL_MODULE_FILENAME

يتيح لك هذا المتغير الاختياري إلغاء الأسماء التي يستخدمها نظام الإصدار افتراضيًا للملفات التي ينشئها. على سبيل المثال، إذا كان اسم LOCAL_MODULE هو foo، يمكنك فرض استدعاء النظام للملف الذي ينشئه libnewfoo. يوضح المثال التالي كيفية تحقيق ذلك:

LOCAL_MODULE := foo
LOCAL_MODULE_FILENAME := libnewfoo

بالنسبة إلى وحدة المكتبة المشتركة، يؤدي هذا المثال إلى إنشاء ملف باسم libnewfoo.so.

ملفات LOCAL_SRC_FILES

يتضمّن هذا المتغيّر قائمة بالملفات المصدر التي يستخدمها نظام الإصدار لإنشاء الوحدة النمطية. أدرِج فقط الملفات التي يمرّرها نظام الإصدار إلى المحوِّل البرمجي، لأنّ نظام الإصدار يحتسب تلقائيًا أي تبعيات مرتبطة. تجدر الإشارة إلى أنّه يمكنك استخدام مسارات الملفات النسبية (إلى LOCAL_PATH) والمطلقة.

ننصح بتجنُّب مسارات الملفات المطلقة، لأنّ المسارات النسبية تجعل ملف Android.mk أكثر قابلية للنقل.

LOCAL_CPP_Extension

يمكنك استخدام هذا المتغيّر الاختياري للإشارة إلى امتداد ملف آخر غير .cpp لملفات المصدر C++. على سبيل المثال، يغير السطر التالي الإضافة إلى .cxx (يجب أن يتضمّن الإعداد النقطة.)

LOCAL_CPP_EXTENSION := .cxx

يمكنك استخدام هذا المتغيّر لتحديد إضافات متعددة. على سبيل المثال:

LOCAL_CPP_EXTENSION := .cxx .cpp .cc

LOCAL_CPP_FEATURES

يمكنك استخدام هذا المتغير الاختياري للإشارة إلى أن التعليمات البرمجية تعتمد على ميزات C++ محددة. ويُفعّل علامات برنامج التجميع والرابط الصحيحة أثناء عملية الإنشاء. بالنسبة إلى البرامج الثنائية التي تم إنشاؤها مسبقًا، يحدّد هذا المتغيّر أيضًا الميزات التي يعتمد عليها الثنائي، ما يساعد في ضمان عمل الرابط النهائي بشكل صحيح. ننصحك باستخدام هذا المتغيّر بدلاً من تفعيل -frtti و-fexceptions مباشرةً في تعريف LOCAL_CPPFLAGS.

يتيح استخدام هذا المتغير لنظام الإصدار استخدام العلامات المناسبة لكل وحدة. ويؤدي استخدام LOCAL_CPPFLAGS إلى استخدام المحول البرمجي لكل العلامات المحددة لكل الوحدات بغض النظر عن الحاجة الفعلية.

على سبيل المثال، للإشارة إلى أن التعليمات البرمجية تستخدم RTTI (معلومات نوع وقت التشغيل)، اكتب:

LOCAL_CPP_FEATURES := rtti

للإشارة إلى أن التعليمة البرمجية تستخدم استثناءات C++، اكتب:

LOCAL_CPP_FEATURES := exceptions

يمكنك أيضًا تحديد قيم متعدّدة لهذا المتغيّر. مثلاً:

LOCAL_CPP_FEATURES := rtti features

الترتيب الذي تصف به القيم لا يهم.

LOCAL_C_includeS

يمكنك استخدام هذا المتغيّر الاختياري لتحديد قائمة المسارات ذات الصلة بدليل NDK root، وذلك لإضافته إلى مسار البحث المضمّن عند تجميع جميع المصادر (C وC++ وAssembly). مثلاً:

LOCAL_C_INCLUDES := sources/foo

أو حتى:

LOCAL_C_INCLUDES := $(LOCAL_PATH)/<subdirectory>/foo

حدِّد هذا المتغيّر قبل إعداد أي علامات تضمين مقابلة من خلال LOCAL_CFLAGS أو LOCAL_CPPFLAGS.

يستخدم نظام الإصدار أيضًا مسارات LOCAL_C_INCLUDES تلقائيًا عند تشغيل تصحيح الأخطاء الأصلي باستخدام ndk-gdb.

LOCAL_CFLAGS

يُعيِّن هذا المتغيّر الاختياري علامات برنامج التحويل البرمجي لتمريرها نظام الإصدار عند إنشاء الملفات المصدر C وC++. يمكن أن تكون القدرة على القيام بذلك مفيدة لتحديد تعريفات ماكرو إضافية أو خيارات تجميع. يمكنك استخدام LOCAL_CPPFLAGS لتحديد علامات C++ فقط.

حاول عدم تغيير مستوى التحسين/تصحيح الأخطاء في ملف Android.mk. يمكن لنظام الإصدار التعامل مع هذا الإعداد تلقائيًا بالنيابة عنك، باستخدام المعلومات ذات الصلة في ملف Application.mk. يؤدي القيام بذلك بهذه الطريقة إلى السماح لنظام الإنشاء بإنشاء ملفات بيانات مفيدة يتم استخدامها أثناء تصحيح الأخطاء.

من الممكن تحديد مسارات تضمين إضافية عن طريق كتابة:

LOCAL_CFLAGS += -I<path>,

ومع ذلك، ننصحك باستخدام LOCAL_C_INCLUDES لهذا الغرض، لأنّ ذلك يتيح أيضًا استخدام المسارات المتاحة لتصحيح الأخطاء الأصلية في ndk-gdb.

LOCAL_CPPFLAGS

هي مجموعة اختيارية من علامات برنامج التجميع التي سيتم تمريرها عند إنشاء ملفات مصدر C++ فقط. وستظهر بعد LOCAL_CFLAGS في سطر الأوامر الخاص بالأداة البرمجية. يمكنك استخدام LOCAL_CFLAGS لتحديد علامات لكل من C وC++.

المكتبات المحلية

يخزن هذا المتغير قائمة وحدات المكتبات الثابتة التي تعتمد عليها الوحدة الحالية.

إذا كانت الوحدة الحالية عبارة عن مكتبة مشتركة أو مكتبة قابلة للتنفيذ، سيفرض هذا المتغيّر ربط هذه المكتبات بالبرنامج الثنائي الناتج.

إذا كانت الوحدة الحالية عبارة عن مكتبة ثابتة، يشير هذا المتغير ببساطة إلى أن الوحدات الأخرى اعتمادًا على الوحدة الحالية ستعتمد أيضًا على المكتبات المدرجة.

LOCAL_SHARED_LIBRARIES

هذا المتغيّر هو قائمة وحدات المكتبات المشتركة التي تعتمد عليها هذه الوحدة في وقت التشغيل. وتكون هذه المعلومات ضرورية في وقت الرابط ولتضمين المعلومات المقابلة في الملف الذي تم إنشاؤه.

المكتبات المحلية_للكامل

يمثّل هذا المتغيّر أحد خيارات LOCAL_STATIC_LIBRARIES، ويوضّح أنّ الرابط يجب أن يتعامل مع وحدات المكتبة المرتبطة على أنّها أرشيفات كاملة. للحصول على مزيد من المعلومات حول الأرشيفات بالكامل، يمكنك الاطلاع على وثائق GNU ld للعلامة --whole-archive.

يكون هذا المتغير مفيدًا عندما تكون هناك تبعيات دائرية بين العديد من المكتبات الثابتة. عند استخدام هذا المتغير لإنشاء مكتبة مشتركة، سيفرض على نظام الإصدار إضافة جميع ملفات الكائنات من مكتباتك الثابتة إلى البرنامج الثنائي النهائي. ومع ذلك، ليس كذلك وذلك عند إنشاء ملفات قابلة للتنفيذ.

LOCAL_LDLIBS

يحتوي هذا المتغيّر على قائمة بعلامات الرابط الإضافية لاستخدامها في إنشاء مكتبتك المشتركة أو الملف التنفيذي. وهي تتيح لك استخدام البادئة -l لتمرير اسم مكتبات النظام المحدّدة. على سبيل المثال، يطلب المثال التالي من الرابط إنشاء وحدة ترتبط بالسمة /system/lib/libz.so في وقت التحميل:

LOCAL_LDLIBS := -lz

للاطّلاع على قائمة مكتبات النظام التي تم الكشف عنها والتي يمكنك الربط بها في إصدار NDK هذا، يُرجى مراجعة واجهات برمجة التطبيقات الأصلية.

LOCAL_LDFLAGS

قائمة علامات الروابط الأخرى لنظام الإصدار لاستخدامها عند إنشاء مكتبتك المشتركة أو قابلة للتنفيذ. على سبيل المثال، لاستخدام رابط ld.bfd على ARM/X86:

LOCAL_LDFLAGS += -fuse-ld=bfd

LOCAL_ALLOW_UNDEFINED_SYMBOLS

بشكل تلقائي، عندما يصادف نظام الإصدار مرجعًا غير محدّد تم رصده أثناء محاولة إنشاء مستند مشترك، سيعرِض الخطأ رمز غير محدّد. يمكن أن يساعدك هذا الخطأ في اكتشاف الأخطاء في التعليمات البرمجية المصدر.

لإيقاف عملية التحقّق هذه، اضبط المتغيّر على true. لاحظ أن هذا الإعداد قد يؤدي إلى تحميل المكتبة المشتركة في وقت التشغيل.

وضع_ARM_LOCAL

ينشِئ نظام الإصدار تلقائيًا برامج ثنائية مستهدفة ضمن ARM في وضع thumb، حيث يبلغ عرض كل تعليمات 16 بت ومرتبطة بمكتبات STL في دليل thumb/. يؤدي تحديد هذا المتغيّر باسم arm إلى فرض إنشاء ملفات كائنات الوحدة على نظام الإنشاء في وضع arm 32 بت. يوضح المثال التالي كيفية القيام بذلك:

LOCAL_ARM_MODE := arm

يمكنك أيضًا توجيه نظام الإصدار لإنشاء مصادر محدّدة فقط في وضع arm من خلال إلحاق اللاحقة .arm بأسماء ملفات المصدر. على سبيل المثال، يطلب المثال التالي من نظام الإصدار تجميع bar.c دائمًا في وضع ARM، ولكن يجب إنشاء foo.c وفقًا للقيمة LOCAL_ARM_MODE.

LOCAL_SRC_FILES := foo.c bar.c.arm

LOCAL_ARM_NEON

لا يهم هذا المتغيّر إلا عند استهداف واجهة التطبيق الثنائية (ABI) في armeabi-v7a. وهو يتيح استخدام خوارزمي ARM Advanced SIMD (NEON) في مصادر C وC++ ، بالإضافة إلى تعليمات NEON في ملفات التجميع.

يُرجى العلم أنّ بعض وحدات المعالجة المركزية (CPU) المستندة إلى ARMv7 لا تتوافق مع إضافات مجموعة تعليمات NEON. لهذا السبب، يجب إجراء اكتشاف وقت التشغيل لتتمكن من استخدام هذه التعليمة البرمجية بأمان في وقت التشغيل. لمزيد من المعلومات، يمكنك الاطّلاع على دعم Neon وميزات وحدة المعالجة المركزية (CPU).

يمكنك بدلاً من ذلك استخدام اللاحقة .neon لتحديد أنّ نظام الإصدار يجمع ملفات مصدر محدَّدة فقط مع دعم NEON. في المثال التالي، يجمع نظام الإنشاء foo.c مع دعم الإبهام والنيون، وbar.c مع دعم الإبهام، وzoo.c مع دعم ARM وNEON:

LOCAL_SRC_FILES = foo.c.neon bar.c zoo.c.arm.neon

إذا كنت تستخدم كلتا اللاحقتين، يجب أن يسبق .arm القيمة .neon.

LOCAL_DISABLE_FORMAT_STRING_CHECKS

يجمِّع نظام الإصدار تلقائيًا الرمز مع حماية سلسلة التنسيق. يؤدي ذلك إلى فرض خطأ في برنامج التحويل البرمجي في حال استخدام سلسلة تنسيق غير ثابتة في دالة من نمط printf. تكون هذه الحماية مفعّلة بشكل تلقائي، ولكن يمكنك إيقافها من خلال ضبط قيمة هذا المتغيّر على true. لا ننصح بذلك بدون سبب مقنع

LOCAL_EXPORT_CFLAGS

يسجِّل هذا المتغيّر مجموعة من علامات برنامج المحول البرمجي C/C++ لإضافتها إلى تعريف LOCAL_CFLAGS لأي وحدة أخرى تستخدم هذه الوحدة من خلال متغيري LOCAL_STATIC_LIBRARIES أو LOCAL_SHARED_LIBRARIES.

على سبيل المثال، ضع في الاعتبار زوج الوحدتين التاليتين: foo وbar، واللذَين يعتمدان على foo:

include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo/foo.c
LOCAL_EXPORT_CFLAGS := -DFOO=1
include $(BUILD_STATIC_LIBRARY)


include $(CLEAR_VARS)
LOCAL_MODULE := bar
LOCAL_SRC_FILES := bar.c
LOCAL_CFLAGS := -DBAR=2
LOCAL_STATIC_LIBRARIES := foo
include $(BUILD_SHARED_LIBRARY)

هنا، يمرّر نظام الإصدار العلامتين -DFOO=1 و-DBAR=2 إلى المحول البرمجي عند إنشاء bar.c. وهي تُضيف أيضًا العلامات التي تم تصديرها في LOCAL_CFLAGS الخاصة بوحدتك حتى تتمكّن من تجاوزها بسهولة.

بالإضافة إلى ذلك، فإنّ العلاقة بين الوحدات هي علاقة انتقالية: إذا كانت السمة zoo تعتمد على السمة bar التي تعتمد بدورها على foo، يكتسب zoo أيضًا جميع العلامات التي تم تصديرها من foo.

أخيرًا، لا يستخدم نظام الإصدار العلامات التي تم تصديرها عند إنشائه محليًا (أي تصميم الوحدة التي يتم تصدير علاماتها). وبالتالي، في المثال أعلاه، لا تمرّر -DFOO=1 إلى المحول البرمجي عند إنشاء foo/foo.c. لإنشاء الإصدار محليًا، استخدِم LOCAL_CFLAGS بدلاً من ذلك.

LOCAL_EXPORT_CPPFLAGS

هذا المتغير هو نفسه LOCAL_EXPORT_CFLAGS، ولكن لعلامات C++ فقط.

LOCAL_EXport_C_includeS

هذا المتغيّر هو نفسه LOCAL_EXPORT_CFLAGS، ولكن في C تشمل المسارات. وهو مفيد في الحالات التي، فيها، على سبيل المثال، تحتاج bar.c إلى تضمين عناوين من الوحدة foo.

LOCAL_EXPORT_LDFLAGS

هذا المتغيّر مماثل لـ LOCAL_EXPORT_CFLAGS، ولكن مع علامات الرابط.

LOCAL_EXport_LDLIBS

هذا المتغيّر هو نفسه LOCAL_EXPORT_CFLAGS، إذ يطلب من نظام الإصدار تمرير أسماء مكتبات نظام معيّنة إلى المحول البرمجي. أضِف -l إلى اسم كل مكتبة تحدّدها.

يُرجى العِلم أنّ نظام الإصدار يُلحق علامات الرابط التي تم استيرادها بقيمة متغيّر LOCAL_LDLIBS في الوحدة. يحدث ذلك بسبب الطريقة التي تعمل بها روابط Unix.

عادةً ما يكون هذا المتغيّر مفيدًا عندما تكون الوحدة foo مكتبة ثابتة وتحتوي على رمز يعتمد على مكتبة نظام. يمكنك بعد ذلك استخدام LOCAL_EXPORT_LDLIBS لتصدير التبعية. مثلاً:

include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo/foo.c
LOCAL_EXPORT_LDLIBS := -llog
include $(BUILD_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := bar
LOCAL_SRC_FILES := bar.c
LOCAL_STATIC_LIBRARIES := foo
include $(BUILD_SHARED_LIBRARY)

في هذا المثال، يضع نظام الإصدار -llog في نهاية أمر linker عندما ينشئ libbar.so. يؤدي إجراء ذلك إلى إعلام الرابط بأنّ libbar.so يعتمد على foo، وبالتالي يعتمد أيضًا على مكتبة تسجيل النظام.

LOCAL_SHORT_COMMANDS

اضبط هذا المتغيّر على true عندما تحتوي الوحدة على عدد كبير جدًا من المصادر و/أو المكتبات الثابتة أو المشتركة التابعة. يؤدي ذلك إلى إجبار نظام الإصدار على استخدام بنية @ للأرشيفات التي تحتوي على ملفات عناصر وسيطة أو ربط مكتبات.

يمكن أن تكون هذه الميزة مفيدة على نظام التشغيل Windows، حيث يقبل سطر الأوامر 8191 حرفًا كحدّ أقصى، وهو الحدّ الأقصى المسموح به للمشروعات المعقّدة. كما يؤثر ذلك في تجميع ملفات المصدر الفردية، مع وضع جميع علامات المحول البرمجي تقريبًا داخل ملفات القائمة أيضًا.

تجدر الإشارة إلى أن أي قيمة بخلاف true سوف تعود إلى السلوك التلقائي. يمكنك أيضًا تحديد APP_SHORT_COMMANDS في ملف Application.mk لفرض هذا السلوك على جميع الوحدات في مشروعك.

لا ننصح بتفعيل هذه الميزة تلقائيًا، لأنّها تجعل الإصدار أبطأ.

LOCAL_THIN_Archive

اضبط هذا المتغيّر على true عند إنشاء مكتبات ثابتة. سيؤدي ذلك إلى إنشاء أرشيف سطحي، وهو ملف مكتبة لا يحتوي على ملفات كائنات، بل مجرد مسارات ملفات إلى الكائنات الفعلية التي تحتوي عليها عادةً.

ويكون ذلك مفيدًا في تقليل حجم ناتج الإصدار. ولكن العيب هو أنّ هذه المكتبات لا يمكن نقلها إلى مكان مختلف (تكون جميع المسارات داخلها نسبية).

القيم الصالحة هي true أو false أو فارغة. يمكن ضبط قيمة تلقائية في ملف Application.mk من خلال المتغيّر APP_THIN_ARCHIVE.

فلتر LOCAL_FILTER_ASM

حدِّد هذا المتغيّر كأمر واجهة أوامر سيستخدمه نظام الإصدار لفلترة ملفات التجميع المستخرَجة أو التي تم إنشاؤها من الملفات التي حدّدتها لـ LOCAL_SRC_FILES. يؤدي تعريف هذا المتغير إلى حدوث الأشياء التالية:

  1. ينشئ نظام الإصدار ملف تجميع مؤقتًا من أي ملف مصدر C أو C++، بدلاً من تجميعه في ملف كائن.
  2. ينفِّذ نظام الإصدار أمر Shell في LOCAL_FILTER_ASM على أي ملف تجميع مؤقت وعلى أي ملف تجميع مُدرَج في LOCAL_SRC_FILES، وبالتالي إنشاء ملف تجميع مؤقت آخر.
  3. يجمع نظام الإصدار ملفات التجميع التي تمت تصفيتها في ملف كائن.

مثلاً:

LOCAL_SRC_FILES  := foo.c bar.S
LOCAL_FILTER_ASM :=

foo.c --1--> $OBJS_DIR/foo.S.original --2--> $OBJS_DIR/foo.S --3--> $OBJS_DIR/foo.o
bar.S                                 --2--> $OBJS_DIR/bar.S --3--> $OBJS_DIR/bar.o

يتجاوب "1" مع المحول البرمجي، و"2" مع عامل التصفية، و "3" مع مجمع التجميع. يجب أن يكون عامل التصفية أمر أوامر مستقلاً يأخذ اسم ملف الإدخال كوسيطة الأولى، واسم ملف الإخراج كوسيطة ثانية. مثلاً:

myasmfilter $OBJS_DIR/foo.S.original $OBJS_DIR/foo.S
myasmfilter bar.S $OBJS_DIR/bar.S

وحدات ماكرو للدوال التي توفرها NDK

يشرح هذا القسم وحدات ماكرو الدالة "إنشاء GNU" التي توفرها NDK. استخدِم $(call <function>) لتقييمها، فهي تعرض معلومات نصية.

دليلي

تعرض وحدة الماكرو هذه مسار آخر ملف جعل مضمَّن، وهو عادةً دليل Android.mk الحالي. الدالة my-dir مفيدة لتحديد LOCAL_PATH في بداية ملف Android.mk. مثلاً:

LOCAL_PATH := $(call my-dir)

نظرًا للطريقة التي يعمل بها GNU Make، فإن ما تعرضه وحدة الماكرو هذه هو مسار ملف الإنشاء الأخير الذي أدرجه نظام الإصدار عند تحليل النصوص البرمجية للإصدار. لهذا السبب، يجب عدم استدعاء my-dir بعد تضمين ملف آخر.

بالنظر إلى المثال التالي على سبيل المثال:

LOCAL_PATH := $(call my-dir)

# ... declare one module

include $(LOCAL_PATH)/foo/`Android.mk`

LOCAL_PATH := $(call my-dir)

# ... declare another module

تكمن المشكلة هنا في أنّ المكالمة الثانية إلى my-dir تُعرِّف LOCAL_PATH على أنه $PATH/foo بدلاً من $PATH، لأنّ آخر عملية تضمين تمت الإشارة إليها.

يمكنك تجنُّب هذه المشكلة من خلال وضع تضمينات إضافية بعد كل شيء آخر في ملف Android.mk. مثلاً:

LOCAL_PATH := $(call my-dir)

# ... declare one module

LOCAL_PATH := $(call my-dir)

# ... declare another module

# extra includes at the end of the Android.mk file
include $(LOCAL_PATH)/foo/Android.mk

إذا لم يكن بالإمكان تنظيم الملف بهذه الطريقة، يمكنك حفظ قيمة استدعاء my-dir الأول في متغيّر آخر. مثلاً:

MY_LOCAL_PATH := $(call my-dir)

LOCAL_PATH := $(MY_LOCAL_PATH)

# ... declare one module

include $(LOCAL_PATH)/foo/`Android.mk`

LOCAL_PATH := $(MY_LOCAL_PATH)

# ... declare another module

all-subdir-makefiles

تعرض قائمة ملفات Android.mk الموجودة في جميع الأدلة الفرعية لمسار my-dir الحالي.

يمكنك استخدام هذه الدالة لتوفير تسلسلات هرمية لدليل المصدر المتداخلة إلى نظام الإنشاء. بشكل تلقائي، يبحث NDK فقط عن الملفات في الدليل الذي يحتوي على ملف Android.mk.

ملف الإنشاء هذا

تعرض مسار الملف الشخصي الحالي (الذي يُسمى منه نظام الإنشاء بالدالة).

ملف أصلي

تعرض مسار الملف الشخصي الرئيسي في شجرة التضمين (مسار ملف makefile الذي يتضمّن الملف الحالي).

ملف التعريف للآباء

تعرض مسار الملف الشخصي الرئيسي في شجرة التضمين (مسار الملف الشخصي الذي يتضمن الملف الحالي).

استيراد-وحدة

دالة تسمح لك بالعثور على ملف Android.mk الخاص بالوحدة وتضمينها حسب اسم الوحدة. وفي ما يلي مثال نموذجي:

$(call import-module,<name>)

في هذا المثال، يبحث نظام الإصدار عن الوحدة التي تم وضع علامة <name> عليها في قائمة الأدلة التي تشير إلى أنّ مراجع المتغيرات في بيئة NDK_MODULE_PATH، يتضمّن ملف Android.mk الخاص بها تلقائيًا بالنيابة عنك.