בדף הזה מתוארים התחביר של קובץ ה-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 שנעשה בה שימוש לכל מעבד וארכיטקטורה נתמכים.
מעבד (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. כל תיאור של מודול צריך להתאים לתהליך הבסיסי הבא:
- מאתחלים או מבטלים את ההגדרה של המשתנים שמשויכים למודול באמצעות המשתנה
CLEAR_VARS
. - מקצים ערכים למשתנים שמשמשים לתיאור המודול.
- מגדירים את מערכת ה-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
. הגדרת המשתנה הזה גורמת לשינויים הבאים:
- מערכת ה-build יוצרת קובץ הרכבה זמני מכל קובץ מקור מסוג C או C++, במקום להדר אותם לקובץ אובייקט.
- מערכת ה-build מריצים את פקודת המעטפת ב-
LOCAL_FILTER_ASM
בכל קובץ הרכבה זמני ובכל קובץ הרכבה שרשום ב-LOCAL_SRC_FILES
, וכך נוצרת קובץ הרכבה זמני נוסף. - מערכת ה-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
שלו.