Android.mk

בדף הזה מתוארים התחביר של קובץ ה-build Android.mk שבו ndk-build משתמש.

סקירה כללית

הקובץ Android.mk נמצא בספריית משנה של ספריית jni/ של הפרויקט, ומתאר את המקורות והספריות המשותפות למערכת ה-build. זה בעצם מקטע קטן של קובץ GNU שמערכת ה-build מנתחת פעם או יותר. קובץ Android.mk שימושי להגדרת הגדרות ברמת הפרויקט שלא מוגדרות ב-Application.mk, במערכת ה-build ובמשתני הסביבה. אפשר גם לשנות את ההגדרות ברמת הפרויקט עבור מודולים ספציפיים.

התחביר של Android.mk מאפשר לקבץ את המקורות למודולים. מודול הוא ספרייה סטטית, ספרייה משותפת או קובץ הפעלה עצמאי. אפשר להגדיר מודול אחד או יותר בכל קובץ Android.mk, וניתן להשתמש באותו קובץ מקור במספר מודולים. מערכת ה-build שומרת רק ספריות משותפות בחבילת האפליקציה. בנוסף, אפשר ליצור ספריות משותפות מתוך ספריות סטטיות.

בנוסף לאריזת ספריות, מערכת ה-build מטפלת במגוון פרטים אחרים בשבילכם. לדוגמה, לא צריך להציג רשימה של קובצי הכותרות או יחסי תלות מפורשים בין קבצים שנוצרו בקובץ Android.mk. מערכת ה-build של NDK מחשבת את הקשרים האלה באופן אוטומטי בשבילכם. כתוצאה מכך, תוכלו ליהנות מתמיכה בפלטפורמות או בכלים חדשים במהדורות NDK עתידיות בלי שתצטרכו לגעת בקובץ Android.mk.

התחביר של הקובץ הזה דומה מאוד לזה שמשמש בקבצים Android.mk שמופצים עם פרויקט Android Open Source המלא. ההטמעה של מערכת ה-build שמשתמשת בהם שונה, אבל הדמיון ביניהם הוא החלטה מודעת בתכנון שמטרתה להקל על מפתחי אפליקציות לעשות שימוש חוזר בקוד המקור של ספריות חיצוניות.

יסודות

לפני שנבחן את התחביר בפירוט, כדאי להתחיל בהבנת היסודות של מה שקובץ Android.mk מכיל. לשם כך, בקטע הזה נעזרים בקובץ Android.mk שבמדגם Hello-JNI, ומסבירים את התפקיד של כל שורה בקובץ.

קובץ Android.mk חייב להתחיל בהגדרת המשתנה LOCAL_PATH:

LOCAL_PATH := $(call my-dir)

המשתנה הזה מציין את המיקום של קובצי המקור בעץ הפיתוח. כאן, פונקציית המאקרו my-dir, שסופקה על ידי מערכת ה-build, מחזירה את הנתיב של הספרייה הנוכחית (הספרייה שמכילה את הקובץ Android.mk עצמו).

השורה הבאה מצהירה על המשתנה CLEAR_VARS, שהערך שלו מספק מערכת ה-build.

include $(CLEAR_VARS)

המשתנה CLEAR_VARS מפנה לקובץ GNU Maker מיוחד שינקה בשבילכם משתני LOCAL_XXX, כמו LOCAL_MODULE, LOCAL_SRC_FILES ו-LOCAL_STATIC_LIBRARIES. שימו לב שהיא לא מנקה את LOCAL_PATH. המשתנה הזה חייב לשמור על הערך שלו כי המערכת מנתחת את כל קובצי הבקרה של ה-build בהקשר ביצוע אחד של GNU Make שבו כל המשתנים הם גלובליים. צריך להצהיר על המשתנה הזה (מחדש) לפני שמתארים כל מודול.

לאחר מכן, המשתנה LOCAL_MODULE שומר את שם המודול שרוצים ליצור. צריך להשתמש במשתנה הזה פעם אחת לכל מודול באפליקציה.

LOCAL_MODULE := hello-jni

כל שם של מודול חייב להיות ייחודי ולא להכיל רווחים. כשמערכת ה-build יוצרת את הקובץ הסופי של הספרייה המשותפת, היא מוסיפה באופן אוטומטי את הקידומת והסיומת המתאימות לשם שהקצית ל-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 של הדוגמה באמצעות הפקודה Sample: Native-activity. לבסוף, בקטע משתנים ומאקרוסים מפורט מידע נוסף על המשתנים מהקטע הזה.

משתנים ופקודות מאקרו

מערכת ה-build מספקת הרבה משתנים אפשריים לשימוש בקובץ Android.mk. רבים מהמשתנים האלה מגיעים עם ערכים שהוקצו מראש. את האחרים, אתם מקצים.

בנוסף למשתנים האלה, אפשר גם להגדיר משתנים שרירותיים משלכם. אם תעשו זאת, חשוב לזכור שמערכת ה-build של NDK שומרת לעצמה את שמות המשתנים הבאים:

  • שמות שמתחילים ב-LOCAL_, כמו LOCAL_MODULE.
  • שמות שמתחילים ב-PRIVATE_, ב-NDK_ או ב-APP. מערכת ה-build משתמשת בהם באופן פנימי.
  • שמות באותיות קטנות, כמו my-dir. מערכת ה-build משתמשת בהם גם באופן פנימי.

אם אתם צריכים להגדיר משתני נוחות משלכם בקובץ Android.mk, מומלץ להוסיף את הקידומת MY_ לשמות שלהם.

משתני הכללה שמוגדרים על ידי NDK

בקטע הזה מוסבר על משתני GNU Make שהמערכת ליצירת גרסאות build מגדירה לפני הניתוח של הקובץ Android.mk. בנסיבות מסוימות, יכול להיות ש-NDK ינתח את הקובץ Android.mk כמה פעמים, תוך שימוש בהגדרה שונה לכל אחד מהמשתנים האלה בכל פעם.

CLEAR_VARS

המשתנה הזה מפנה לסקריפט של build שמגדיר כמעט את כל המשתנים של LOCAL_XXX שמפורטים בקטע 'משתנים בהגדרת המפתח' שבהמשך. משתמשים במשתנה הזה כדי לכלול את הסקריפט הזה לפני שמתארים מודול חדש. התחביר לשימוש בו הוא:

include $(CLEAR_VARS)

BUILD_EXECUTABLE

המשתנה מפנה לסקריפט של build שאוסף את כל המידע על המודול שסיפקתם במשתנים של LOCAL_XXX, וקובע איך ליצור יעד הפעלה מהמקורות שציינתם. חשוב לזכור שכדי להשתמש בסקריפט הזה, צריך להקצות ערכים למשתנים LOCAL_MODULE ו-LOCAL_SRC_FILES לפחות (מידע נוסף על המשתנים האלה זמין במאמר משתני תיאור של מודולים).

התחביר לשימוש במשתנה הזה הוא:

include $(BUILD_EXECUTABLE)

BUILD_SHARED_LIBRARY

המשתנה הזה מפנה לסקריפט build שאוסף את כל המידע על המודול שסיפקתם במשתני LOCAL_XXX, ומחליט איך ליצור ספרייה משותפת יעד מהמקורות שציינתם. חשוב לזכור שכדי להשתמש בסקריפט הזה, צריך להקצות ערכים למשתנים LOCAL_MODULE ו-LOCAL_SRC_FILES לפחות (מידע נוסף על המשתנים האלה זמין במאמר משתני תיאור של מודולים).

התחביר לשימוש במשתנה הזה הוא:

include $(BUILD_SHARED_LIBRARY)

משתנה של ספרייה משותפת גורם למערכת ה-build ליצור קובץ ספרייה עם סיומת .so.

BUILD_STATIC_LIBRARY

וריאנט של BUILD_SHARED_LIBRARY המשמש ליצירת ספרייה סטטית. מערכת ה-build לא מעתיקה ספריות סטטיות לפרויקט או לחבילות, אבל היא יכולה להשתמש בהן כדי ליצור ספריות משותפות (ראו LOCAL_STATIC_LIBRARIES ו-LOCAL_WHOLE_STATIC_LIBRARIES בהמשך). התחביר לשימוש במשתנה הזה הוא:

include $(BUILD_STATIC_LIBRARY)

משתנה של ספרייה סטטית גורם למערכת ה-build ליצור ספרייה עם סיומת .a.

PREBUILT_SHARED_LIBRARY

מצביע על סקריפט build שמשמש לציון ספרייה משותפת שהוגדרה מראש. בניגוד במקרה של BUILD_SHARED_LIBRARY ו-BUILD_STATIC_LIBRARY, כאן הערך של LOCAL_SRC_FILES לא יכול להיות קובץ מקור. במקום זאת, צריך לציין נתיב יחיד לספרייה משותפת שנוצרה מראש, כמו foo/libfoo.so. התחביר לשימוש במשתנה הזה הוא:

include $(PREBUILT_SHARED_LIBRARY)

אתם יכולים גם להפנות לספרייה שהוגדרה מראש במודול אחר באמצעות המשתנה LOCAL_PREBUILTS. למידע נוסף על השימוש בספריות מוכנות מראש

PREBUILT_STATIC_LIBRARY

זהה ל-PREBUILT_SHARED_LIBRARY, אבל לספרייה סטטית שנוצרה מראש. למידע נוסף על שימוש בספריות מוכנות מראש, ראו שימוש בספריות מוכנות מראש.

משתני מידע על היעד

מערכת ה-build מנתחת את Android.mk פעם לכל ABI שצוין על ידי המשתנה APP_ABI, שבדרך כלל מוגדר בקובץ Application.mk. אם הערך של APP_ABI הוא all, מערכת ה-build תנתח את Android.mk פעם לכל ABI שנתמך ב-NDK. בקטע הזה מתוארים המשתנים שמערכת ה-build מגדירה בכל פעם שהיא מנתחת את Android.mk.

TARGET_ARCH

משפחת המעבדים שמערכת ה-build מטרגטת בזמן הניתוח של הקובץ Android.mk. המשתנה יהיה אחד מהערכים הבאים: arm, arm64, x86 או x86_64.

TARGET_PLATFORM

מספר רמת ה-API של Android שמערכת ה-build מטרגטת בזמן הניתוח של הקובץ Android.mk. לדוגמה, תמונות המערכת של Android 5.1 מתאימות לרמת API של Android 22: android-22. רשימה מלאה של שמות הפלטפורמות ותמונות המערכת התואמות של Android מופיעה במאמר ממשקי API מקומיים. בדוגמה הבאה מופיע התחביר לשימוש במשתנה הזה:

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

TARGET_ARCH_ABI

ה-ABI שמערכת ה-build מטרגטת בזמן שהיא מנתחת את קובץ ה-Android.mk הזה. בטבלה 1 מוצגת הגדרת ה-ABI שנעשה בה שימוש לכל מעבד וארכיטקטורה נתמכים.

טבלה 1. הגדרות ABI למעבדים ולארכיטקטורות שונים.

מעבד (CPU) וארכיטקטורה הגדרה
ARMv7 armeabi-v7a
ARMv8 AArch64 arm64-v8a
i686 x86
x86-64 x86_64

בדוגמה הבאה מוסבר איך לבדוק אם ARMv8 AArch64 הוא שילוב היעד של המעבד ו-ABI:

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

לפרטים נוספים על ממשקי ABI של ארכיטקטורה ועל בעיות תאימות משויכות, אפשר לעיין במאמר ממשקי ABI של Android.

בעתיד, ליעדים חדשים של ABI יהיו ערכים שונים.

TARGET_ABI

שרשור של רמת ה-API לטירגוט ב-Android ו-ABI. זה שימושי במיוחד כשרוצים לבדוק תמונה של מערכת יעד ספציפית במכשיר אמיתי. לדוגמה, כדי לבדוק אם יש מכשיר ARM עם 64 ביט שפועל עם Android API ברמה 22:

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

משתנים של תיאור מודול

המשתנים בקטע הזה מתארים את המודול למערכת ה-build. כל תיאור של מודול צריך להתאים לתהליך הבסיסי הבא:

  1. מאתחלים או מבטלים את ההגדרה של המשתנים שמשויכים למודול באמצעות המשתנה CLEAR_VARS.
  2. מקצים ערכים למשתנים שמשמשים לתיאור המודול.
  3. מגדירים את מערכת ה-build של NDK להשתמש בסקריפט ה-build המתאים למודול באמצעות המשתנה BUILD_XXX.

LOCAL_PATH

המשתנה הזה משמש כדי לתת את הנתיב של הקובץ הנוכחי. צריך להגדיר אותה בתחילת הקובץ Android.mk. הדוגמה הבאה ממחישה איך לעשות זאת:

LOCAL_PATH := $(call my-dir)

הסקריפט שאליו נקודות CLEAR_VARS לא מנקה את המשתנה הזה. לכן, צריך להגדיר אותו רק פעם אחת, גם אם קובץ Android.mk מתאר כמה מודולים.

LOCAL_MODULE

המשתנה הזה שומר את שם המודול שלכם. השם חייב להיות ייחודי מבין כל שמות המודולים, ולא יכול להכיל רווחים. צריך להגדיר אותו לפני שמוסיפים סקריפטים (מלבד הסקריפט של CLEAR_VARS). אין צורך להוסיף את הקידומת lib או את סיומת הקובץ .so או .a. מערכת ה-build מבצעת את השינויים האלה באופן אוטומטי. בכל הקבצים ב-Android.mk וב-Application.mk, מפנים למודול בשם שלא השתנה. לדוגמה, השורה הבאה יוצרת מודול של ספרייה משותפת שנקרא libfoo.so:

LOCAL_MODULE := "foo"

אם רוצים שהמודול שנוצר יהיה בעל שם שונה מ-lib + הערך של LOCAL_MODULE, אפשר להשתמש במשתנה LOCAL_MODULE_FILENAME כדי לתת למודול שנוצר שם לבחירתכם.

LOCAL_MODULE_FILENAME

המשתנה האופציונלי הזה מאפשר לשנות את השמות שמערכת ה-build משתמשת בהם כברירת מחדל לקבצים שהיא יוצרת. לדוגמה, אם השם של LOCAL_MODULE הוא foo, אפשר לאלץ את המערכת לקרוא לקובץ שהיא יוצרת libnewfoo. הדוגמה הבאה ממחישה איך לעשות זאת:

LOCAL_MODULE := foo
LOCAL_MODULE_FILENAME := libnewfoo

לדוגמה, מודול של ספרייה משותפת ייצור קובץ בשם libnewfoo.so.

LOCAL_SRC_FILES

המשתנה הזה מכיל את רשימת קובצי המקור שבהם מערכת ה-build משתמשת כדי ליצור את המודול. עליכם לרשום רק את הקבצים שמערכת ה-build מעבירה בפועל למהדר, כי מערכת ה-build מחשבת באופן אוטומטי את כל יחסי התלות המשויכים. שימו לב שאפשר להשתמש גם בנתיבים יחסיים (ל-LOCAL_PATH) וגם בנתיבים מוחלטים של קבצים.

מומלץ להימנע מנתיבי קבצים מוחלטים. נתיבי קבצים יחסיים מאפשרים להעביר את הקובץ Android.mk בקלות רבה יותר.

LOCAL_CPP_תוספים

אפשר להשתמש במשתנה האופציונלי הזה כדי לציין סיומת קובץ שאינה .cpp בשביל קובצי המקור מסוג C++. לדוגמה, השורה הבאה משנה את התוסף ל-.cxx. (ההגדרה חייבת לכלול את הנקודה).

LOCAL_CPP_EXTENSION := .cxx

ניתן להשתמש במשתנה הזה כדי לציין כמה תוספים. לדוגמה:

LOCAL_CPP_EXTENSION := .cxx .cpp .cc

LOCAL_CPP_FEATURES

תוכלו להשתמש במשתנה האופציונלי הזה כדי לציין שהקוד מסתמך על תכונות ספציפיות של C++. הוא מפעיל את דגלי המהדר והקישור הנכונים במהלך תהליך ה-build. בקובצי בינארי שנוצרו מראש, המשתנה הזה גם מציין את התכונות שבהן הקובץ הבינארי תלוי, וכך עוזר לוודא שהקישור הסופי פועל כמו שצריך. מומלץ להשתמש במשתנה הזה במקום להפעיל את -frtti ואת -fexceptions ישירות בהגדרה של LOCAL_CPPFLAGS.

השימוש במשתנה הזה מאפשר למערכת ה-build להשתמש בדגלים המתאימים לכל מודול. שימוש ב-LOCAL_CPPFLAGS גורם למהדר להשתמש בכל הדגלים שצוינו לכל המודולים, ללא קשר לצורך בפועל.

לדוגמה, כדי לציין שהקוד משתמש ב-RTTI (RunTime Type Information), כותבים:

LOCAL_CPP_FEATURES := rtti

כדי לציין שהקוד משתמש בחריגים של C++, כותבים:

LOCAL_CPP_FEATURES := exceptions

אפשר גם לציין כמה ערכים למשתנה הזה. לדוגמה:

LOCAL_CPP_FEATURES := rtti features

הסדר שבו מתארים את הערכים לא חשוב.

LOCAL_C_INCLUDES

אפשר להשתמש במשתנה האופציונלי הזה כדי לציין רשימת נתיבים, ביחס לספרייה root של NDK, שנוספים לנתיב החיפוש של ה-include בזמן הידור כל המקורות (C,‏ C++ ו-Assembly). לדוגמה:

LOCAL_C_INCLUDES := sources/foo

או אפילו:

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

צריך להגדיר את המשתנה לפני שמגדירים דגלי הכללה תואמים באמצעות LOCAL_CFLAGS או LOCAL_CPPFLAGS.

מערכת ה-build משתמשת גם בנתיבי LOCAL_C_INCLUDES באופן אוטומטי כשמפעילים ניפוי באגים מקורי באמצעות ndk-gdb.

LOCAL_ASFLAGS

סימונים שמועברים ל-Clang כשבונים קובצי .s או .S.

LOCAL_ASMFLAGS

דגלים שיועברו ל-yasm בזמן ה-build של קבצים מסוג .asm.

LOCAL_CFLAGS

דגלים שיועברו ל-Clang בזמן ה-build של קובצי מקור של C,‏ C++‎ וחלק מ-assembly‏ (.s ו-.S, אבל לא .asm). היכולת לעשות זאת יכולה להיות שימושית כדי לציין הגדרות מאקרו או אפשרויות הידור נוספות. משתמשים ב-LOCAL_CPPFLAGS כדי לציין דגלים ל-C++ בלבד. משתמשים ב-LOCAL_CONLYFLAGS כדי לציין דגלים עבור C בלבד.

נסו לא לשנות את רמת האופטימיזציה או ניפוי הבאגים בקובץ Android.mk. מערכת ה-build יכולה לטפל בהגדרה הזו באופן אוטומטי, באמצעות המידע הרלוונטי בקובץ Application.mk. כך מערכת ה-build יכולה ליצור קובצי נתונים שימושיים לצורך ניפוי באגים.

אפשר לציין נתיבי include נוספים על ידי כתיבת:

LOCAL_CFLAGS += -I<path>,

עם זאת, עדיף להשתמש ב-LOCAL_C_INCLUDES למטרה הזו, כי כך תוכלו להשתמש גם בנתיבים שזמינים לניפוי באגים מקומי באמצעות ndk-gdb.

LOCAL_CONLYFLAGS

סימונים שיועברו ל-Clang במהלך הידור של מקורות C. בניגוד ל-LOCAL_CFLAGS, הערך של LOCAL_CONLYFLAGS לא יועבר ל-Clang במהלך הידור מקורות של C++ או של אסמבלר.

LOCAL_CPPFLAGS

קבוצה אופציונלית של דגלים של מהדרים שיועברו בזמן ה-build של קובצי המקור של C++‏ בלבד. הם יופיעו אחרי LOCAL_CFLAGS בשורת הפקודה של המהדר. אפשר להשתמש ב-LOCAL_CFLAGS כדי לציין דגלים גם עבור C וגם עבור C++‎.

LOCAL_staticIC_LIBRARIES

המשתנה הזה מאחסן את רשימת המודולים של הספריות הסטטיות שעליהם המשתנה הנוכחי תלוי.

אם המודול הנוכחי הוא ספרייה משותפת או קובץ הפעלה, המשתנה יאלץ קישור של הספריות האלה לקובץ הבינארי שייווצר.

אם המודול הנוכחי הוא ספרייה סטטית, המשתנה הזה מציין פשוט שמודולים אחרים שתלויים במודול הנוכחי יהיו תלויים גם בספריות שצוינו.

LOCAL_SHARED_LIBRARIES

המשתנה הזה הוא רשימת מודולים של ספריות משותפות שעליהם המשתנה הזה תלוי במהלך זמן הריצה. המידע הזה נחוץ בזמן הקישור, וכדי להטמיע את המידע התואם בקובץ שנוצר.

LOCAL_WHOLE_StatIC_LIBRARIES

המשתנה הזה הוא וריאנט של LOCAL_STATIC_LIBRARIES, ומציין שהמקשר צריך להתייחס למודולים של הספרייה המשויכים כארכיונים שלמים. למידע נוסף על ארכיונים שלמים, אפשר לעיין במסמכי העזרה של GNU ld לגבי הדגל --whole-archive.

המשתנה הזה שימושי כשיש יחסי תלות מעגליים בין מספר ספריות סטטיות. כשמשתמשים במשתנה הזה כדי ליצור ספרייה משותפת, מערכת ה-build מאלצת את מערכת ה-build להוסיף את כל קובצי האובייקטים מהספריות הסטטיות לקובץ הבינארי הסופי. עם זאת, המצב שונה כשמפתחים קובצי הפעלה.

LOCAL_LDLIBS

המשתנה הזה מכיל את רשימת הדגלים הנוספים של הקישור לשימוש ביצירת הספרייה המשותפת או קובץ ההפעלה. בעזרת הקידומת -l תוכלו להעביר את השם של ספריות מערכת ספציפיות. לדוגמה, הדוגמה הבאה מנחה את המקשר ליצור מודול שמקשר ל-/system/lib/libz.so בזמן הטעינה:

LOCAL_LDLIBS := -lz

בקישור הבא מפורטת רשימת ספריות המערכת החשופות שאפשר לקשר אליהן במהדורת NDK הזו: ממשקי API מקומיים.

LOCAL_LDFLAGS

רשימה של דגלים אחרים לקישור שבהם מערכת ה-build תשתמש כדי ליצור את הספרייה המשותפת או את קובץ ההפעלה. לדוגמה, כדי להשתמש ב-linker ld.bfd ב-ARM/X86:

LOCAL_LDFLAGS += -fuse-ld=bfd

LOCAL_ALLOW_UNDEFINED_SYMBOLS

כברירת מחדל, כשמערכת ה-build נתקלת בהפניה לא מוגדרת בזמן הניסיון ליצור ספרייה משותפת, היא תשליך שגיאה מסוג undefined symbol. השגיאה הזו יכולה לעזור לכם לאתר באגים בקוד המקור.

כדי להשבית את הבדיקה הזו, מגדירים את המשתנה הזה לערך true. שימו לב שההגדרה הזו עשויה לגרום לספרייה המשותפת להיטען בזמן הריצה.

LOCAL_ARM_MODE

כברירת מחדל, מערכת ה-build יוצרת קובצי יעד בינאריים של ARM במצב תמונה ממוזערת, שבו כל הוראה היא ברוחב 16 ביט והיא מקושרת לספריות ה-STL בספרייה thumb/. הגדרת המשתנה הזה כ-arm מאלצת את מערכת ה-build ליצור את קובצי האובייקט של המודול במצב arm של 32 ביט. בדוגמה הבאה מוסבר איך עושים זאת:

LOCAL_ARM_MODE := arm

אפשר גם להורות למערכת ה-build ליצור מקורות ספציפיים רק במצב arm על ידי הוספת הסיומת .arm לשמות הקבצים של המקור. לדוגמה, הדוגמה הבאה מורה למערכת ה-build תמיד לקמפל את bar.c במצב ARM, אבל לבנות את foo.c בהתאם לערך של LOCAL_ARM_MODE.

LOCAL_SRC_FILES := foo.c bar.c.arm

LOCAL_ARM_NEON

המשתנה הזה חשוב רק כשמטרגטים את ה-ABI של armeabi-v7a. היא מאפשרת להשתמש ברכיבים מהותיים של מהדר (compiler) ARM Advanced SIMD (NEON) במקורות C ו-C++ שלכם, וגם בהוראות של NEON בקובצי Assembly.

שימו לב שלא כל המעבדים (CPU) מבוססי ARMv7 תומכים בתוספים של קבוצת ההוראות של NEON. לכן, צריך לבצע זיהוי בסביבת זמן הריצה כדי שתוכלו להשתמש בקוד הזה בבטחה בסביבת זמן הריצה. מידע נוסף זמין במאמרים תמיכה ב-Neon ותכונות המעבד.

לחלופין, אפשר להשתמש בסיומת .neon כדי לציין שמערכת ה-build תדרג רק קובצי מקור ספציפיים עם תמיכה ב-NEON. בדוגמה הבאה, מערכת ה-build מקמפל את foo.c עם תמיכה ב-thumb וב-neon, את bar.c עם תמיכה ב-thumb ואת zoo.c עם תמיכה ב-ARM וב-NEON:

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

אם משתמשים בשתי הסיומות, .arm חייב להקדים את .neon.

LOCAL_DISABLE_FORMAT_STRING_CHECKS

כברירת מחדל, מערכת ה-build מהדרת קוד עם הגנה על מחרוזת פורמט. הפעולה הזו מאלצת שגיאה במהלך הידור אם נעשה שימוש במחרוזת פורמט שאינה קבועה בפונקציה בסגנון printf. ההגנה הזו מופעלת כברירת מחדל, אבל אפשר להשבית אותה על ידי הגדרת הערך של המשתנה הזה ל-true. אנחנו לא ממליצים לעשות זאת ללא סיבה משכנעת.

LOCAL_EXPORT_CFLAGS

המשתנה הזה מתעד קבוצה של דגלי מהדר (compiler) 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)

כאן, מערכת ה-build מעבירה את הדגלים -DFOO=1 ו--DBAR=2 למהדר (compiler) בזמן הבנייה של bar.c. הוא גם מוסיף דגלים שיוצאו ל-LOCAL_CFLAGS של המודול, כך שאפשר לשנות אותם בקלות.

בנוסף, הקשר בין המודולים הוא טרנזיטיבי: אם zoo תלוי בפונקציה bar, שתלויה בתור foo, אז zoo גם יורש את כל הדגלים שיוצאו מ-foo.

לבסוף, מערכת ה-build לא משתמשת בדגלים מיוצאים בזמן הבנייה של המכשיר באופן מקומי (כלומר, בניית המודול שאת הדגלים שלו מייצאים). לכן, בדוגמה שלמעלה, הוא לא מעביר את -DFOO=1 למהדר (compiler) בזמן הבנייה של foo/foo.c. כדי לבנות באופן מקומי, צריך להשתמש ב-LOCAL_CFLAGS במקום זאת.

LOCAL_EXPORT_CPPFLAGS

המשתנה הזה זהה ל-LOCAL_EXPORT_CFLAGS, אבל רק לדגלי C++.

LOCAL_EXPORT_C_INCLUDES

המשתנה הזה זהה למשתנה LOCAL_EXPORT_CFLAGS, אבל עבור נתיבי include של C. היא שימושית במקרים שבהם, לדוגמה, bar.c צריך לכלול כותרות מהמודול foo.

LOCAL_EXPORT_LDFLAGS

המשתנה הזה זהה ל-LOCAL_EXPORT_CFLAGS, אבל עבור דגלים מסוג linker.

LOCAL_EXPORT_LDLIBS

המשתנה הזה זהה ל-LOCAL_EXPORT_CFLAGS, והוא מציין למערכת ה-build להעביר למהדר שמות של ספריות מערכת ספציפיות. מוסיפים את -l בתחילת השם של כל ספרייה שציינתם.

שימו לב שמערכת ה-build מצרפת סימונים מיובאים של מנגנון קישור לערך של משתנה 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)

בדוגמה הזו, מערכת ה-build שמה את -llog בסוף הפקודה של ה-linker כשהיא יוצרת את libbar.so. הפעולה הזו מאפשרת למקשר לדעת ש-libbar.so תלויה ב-foo, ולכן היא תלויה גם בספריית הרישום ביומן המערכת.

LOCAL_SHORT_COMMANDS

מגדירים את המשתנה הזה ל-true כשלמודול יש מספר גדול מאוד של מקורות ו/או ספריות סטטיות או משותפות תלויות. הפעולה הזו מאלצת את מערכת ה-build להשתמש בתחביר @ לארכיונים שמכילים קובצי אובייקט ביניים או ספריות קישור.

התכונה הזו יכולה להיות שימושית ב-Windows, שבה שורת הפקודה מקבלת עד 8,191 תווים, מה שעלול להיות קטן מדי לפרויקטים מורכבים. הוא משפיע גם על האיסוף של קובצי מקור נפרדים, ומציב כמעט את כל דגלי המהדר גם בקובצי רשימה.

חשוב לזכור שכל ערך מלבד true יחזור להתנהגות ברירת המחדל. אפשר גם להגדיר את APP_SHORT_COMMANDS בקובץ Application.mk כדי לאלץ את ההתנהגות הזו בכל המודולים בפרויקט.

לא מומלץ להפעיל את התכונה הזו כברירת מחדל, כי היא מאטה את תהליך ה-build.

LOCAL_THIN_ARCHIVE

מגדירים את המשתנה הזה ל-true כשמפתחים ספריות סטטיות. הפעולה הזו תיצור ארכיון צר, קובץ ספרייה שלא מכיל קובצי אובייקטים, אלא רק נתיבי קובץ לאובייקטים עצמם שהוא בדרך כלל מכיל.

האפשרות הזו שימושית כדי להקטין את הגודל של פלט ה-build. החיסרון הוא שאי אפשר להעביר ספריות כאלה למיקום אחר (כל הנתיבים בתוכן הן יחסיים).

הערכים החוקיים הם true, false או ריקים. אפשר להגדיר ערך ברירת מחדל בקובץ Application.mk באמצעות המשתנה APP_THIN_ARCHIVE.

LOCAL_FILTER_ASM

מגדירים את המשתנה הזה כפקודת מעטפת שבה תשתמש מערכת ה-build כדי לסנן את קובצי האסיפה שחולצו או נוצרו מהקבצים שציינתם בשדה LOCAL_SRC_FILES. הגדרת המשתנה הזה גורמת לשינויים הבאים:

  1. מערכת ה-build יוצרת קובץ הרכבה זמני מכל קובץ מקור מסוג C או C++, במקום להדר אותם לקובץ אובייקט.
  2. מערכת ה-build מריצים את פקודת המעטפת ב-LOCAL_FILTER_ASM בכל קובץ הרכבה זמני ובכל קובץ הרכבה שרשום ב-LOCAL_SRC_FILES, וכך נוצרת קובץ הרכבה זמני נוסף.
  3. מערכת ה-build משלבת את קובצי ההרכבה המסוננים האלה לקובץ אובייקט.

לדוגמה:

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' מייצג את המהדר (compiler), '2' למסנן ו-'3' מייצג את המהדר. המסנן חייב להיות פקודת מעטפת עצמאית שמשתמשת בשם של קובץ הקלט כארגומנט הראשון ובשם של קובץ הפלט בתור הארגומנט השני. לדוגמה:

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

פונקציות מאקרו שסופקו על ידי NDK

קטע זה מסביר את פקודות המאקרו של פונקציית GNU Make שה-NDK מספק. צריך להשתמש בפונקציה $(call <function>) כדי להעריך אותן, והן מחזירות מידע טקסטואלי.

my-dir

המאקרו הזה מחזיר את הנתיב של קובץ ה-makefile האחרון שכלול, שבדרך כלל הוא הספרייה הנוכחית של Android.mk. אפשר להשתמש ב-my-dir כדי להגדיר את LOCAL_PATH בתחילת הקובץ Android.mk. לדוגמה:

LOCAL_PATH := $(call my-dir)

בגלל אופן הפעולה של GNU Maker, המאקרו הזה מחזיר באמת את הנתיב של קובץ ה-Makefile האחרון שמערכת ה-build כללה במהלך ניתוח הסקריפטים של ה-build. לכן, לא צריך להפעיל את 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 הנוכחי.

אפשר להשתמש בפונקציה הזו כדי ליצור למערכת ה-build היררכיות של ספריות מקורות מוטמעות עמוקות. כברירת מחדל, NDK מחפש קבצים רק בתיקייה שמכילה את הקובץ Android.mk.

this-makefile

מחזירה את הנתיב של קובץ ה-Makefile הנוכחי (שממנו מערכת ה-build נקראת פונקציה).

קובץ הורה

הפונקציה מחזירה את הנתיב של קובץ ה-getfile של ההורה בעץ ההכללה (הנתיב של קובץ ה-makefile שכלל את הנוכחי).

קובץ סבא-סבתא

מחזירה את הנתיב של קובץ ה-getfile של הסב בעץ ההכללה (הנתיב של קובץ ה-Makefile שכלל את הקובץ הנוכחי).

import-module

פונקציה שמאפשרת למצוא ולצרף את הקובץ Android.mk של מודול לפי שם המודול. דוגמה אופיינית היא:

$(call import-module,<name>)

בדוגמה הזו, מערכת ה-build מחפשת את המודול שתייגת <name> ברשימת הספריות שמפנות למשתנה הסביבה NDK_MODULE_PATH, וכוללת באופן אוטומטי את הקובץ Android.mk שלו.