makepp_functions - אונליין בענן

זוהי הפקודה makepp_functions שניתן להריץ בספק האירוח החינמי של OnWorks באמצעות אחת מתחנות העבודה המקוונות החינמיות שלנו, כגון Ubuntu Online, Fedora Online, אמולטור מקוון של Windows או אמולטור מקוון של MAC OS.

תָכְנִית:

שֵׁם


makepp_functions -- פונקציות ב-makepp

תיאור


A: שם_קובץ_מוחלט,
שם_קובץ_מוחלט_ללא_קישור,
אבספאט,
הוסף קידומת,
סיומת,
ו, B: שם בסיס, C: שִׂיחָה, D: דיר,
dir_noslash, E: שְׁגִיאָה, F: קובץ subst,
לסנן,
סינון_החוצה,
filter_out_dirs,
קובץ חיפוש,
מצא_ראשון_מעלה,
מצא_תוכנית,
מחרוזת חיפוש,
מצא_כלפי מעלה,
זמין_ראשון,
מילה ראשונה,
עבור כל אחד, I: אם,
אם זה נכון,
מקשר_להסיק,
אובייקטים_להסיק,
מידע, J: לְהִצְטַרֵף, M: עשה,
מפת יצירה,
מייפרל,
מַפָּה,
"mktemp", N: לא דיר, O: נוצר_רק,
רק_לא_מטרות,
מטרות_מזויפות_בלבד,
רק_מעופש,
מטרות_בלבד,
או,
מָקוֹר, P: פטסובסט,
פרל,
מְזוּיָף,
לבנות מראש,
הדפס, R: נתיב אמיתי,
שם_קובץ_יחסי,
יחסית_ל, S: צדף,
סוג,
לְהִתְפַּשֵׁט,
תת-חלק,
סִיוֹמֶת, T: זמני, W: אַזהָרָה,
תו כללי,
מילה,
רשימת מילים,
מילים, X: קסארגס

כל ביטוי בפורמט "$(name)", כאשר "name" אינו שם של משתנה, או
"$(name arg1 arg2 arg3)" מתפרש כקריאה לפונקציה. השם עשוי להכיל אותיות,
קווים תחתונים או מקפים; כדי למנוע בלבול, ניתן להשתמש במקפים או בקווים תחתונים
לסירוגין, מכיוון שמקפים פנימיים מומרים לקווים תחתונים. הערכת כאלה
ביטוי פשוט מפעיל תת-שגרה של פרל. אם "name" מופיע לפני "&" הוא מפעיל את
פקודה או סקריפט מובנים בשם זה בתוך תהליך makepp, ומחזירים את התקן
פלט. זה דורש בניית perl עבור PerlIO. אם השם אינו שם פונקציה
זה הופך לקריאה של קריאה.

כמו עם משתנים, יש לך אפשרות לבחור בין "$(name ...)" או "${name ...}". אם ברצונך
להטמיע את אותו סוגריים, זה חייב להיות משויך, השני לא משנה: "$(name
...(){..." או "${name ...{}(...}". (עם זאת, עבור map ו-perl, הסוגריים הסוגרים הראשונים מסתיים
הביטוי.) הכפלה מאפשרת לארגומנטים להשתרע על פני מספר שורות. השורות החדשות הן
לאחר מכן מטופלים כרווחים, למעט אולי ב-"define". יש גם את התחביר "$[name ...]"
או $[[שם ...]], אשר מוערך בעת קריאת ה-makefile, לפני כללי grokking
ומבנים אחרים.

ל-Makepp מספר פונקציות מובנות שעשויות להיות שימושיות. הוא תומך כמעט בכל...
פונקציות הטקסטואליות של GNU make (ראו את התיעוד של GNU make לפרטים), וחלק מהן
משלך. ניתן להגדיר תת-שגרות של פרל שיעשו כל מה שתרצו. ראו את משפט ה-"sub"
ובסעיף על הרחבת makepp לפרטים נוספים.

מותנה פונקציות
ו תנאי1[,תנאי2[,תנאי3...]]
הפונקציה and מספקת פעולת AND "קצר חשמלי". כל ארגומנט הוא
מורחב, לפי הסדר. אם ארגומנט מתרחב למחרוזת ריקה, העיבוד נעצר ו
תוצאת ההרחבה היא המחרוזת הריקה. אם כל הארגומנטים מתרחבים למחרוזת שאינה
מחרוזת ריקה אז תוצאת ההרחבה היא ההרחבה של הארגומנט האחרון.

if חוט, תוצאה-אם-המחרוזת-אינה-ריקה[, תוצאה-אם-מחרוזת-ריקה]
אם זה נכון חוט, תוצאה-אם-מחרוזת-אמת[, תוצאה-אם-מחרוזת-שקר]
אלטרנטיבה למשפטים "ifeq" וכו'. אם המחרוזת אינה ריקה (כלומר, ה-
(אם התנאי מתקיים), מוחזר הארגומנט השני (הפסקת "אז") (לאחר
הרחבת משתנה); אם המחרוזת ריקה, הארגומנט השלישי (פסוקית "אחרת") הוא
חזר.

לדוגמה,

CFLAGS := $(if $(filter gcc egcc, $(CC)), -g -Wall, -g)

מגדיר CFLAGS כ-"-g -Wall" אם המשתנה CC הוא "gcc" או "egcc", ו-"-g"
אחרת. (זה מה שעושים כללי הבנייה המוגדרים כברירת מחדל.)

""iftrue" דומה ל-"if", אלא שהמחרוזת 0 מטופלת כריקה.

or תנאי1[,תנאי2[,תנאי3...]]
הפונקציה or מספקת פעולת OR "קצר חשמלי". כל ארגומנט מורחב,
לפי הסדר. אם ארגומנט מתרחב למחרוזת שאינה ריקה, העיבוד נעצר וה-
תוצאת ההרחבה היא המחרוזת הזו. אם, לאחר שכל הארגומנטים מורחבים, כל
אם הם false (ריקים), אז תוצאת ההרחבה היא המחרוזת ריקה.

שלח ו שם הקובץ פונקציות
שם_קובץ_מוחלט קבצים
אבפאת קבצים
ממיר שמות קבצים יחסיים לערכים מוחלטים ללא . or ... לדוגמה,
ייתכן ש-"$(absolute_filename xyz.c)" יחזיר את "/usr/src/our_project/subdir/xyz.c".

שם_קובץ_מוחלט_ללא_קישור קבצים
שביל אמיתי קבצים
כמו absolute_filename, אך מבטיח שקישורים סמליים יטופלו.

שם בסיס שמות קבצים
שם הבסיס הוא שם הקובץ כולו (כולל הספרייה), פחות הטקסט שאחריו ו-
כולל הנקודה האחרונה. לדוגמה, "$(basename myfile/version-1.0-module.c)" הוא
"הקובץ/מודול-גרסה-1.0 שלי"

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

dir_noslash שם הקובץ
זהה ל-"$(dir)" פרט לכך שהוא לא מחזיר את הקו הנטוי הנגמר.

קובץ תבנית, תַחֲלִיף, מילים
בצע החלפת תבניות על שמות קבצים. זה שונה מ-patsubst בכך ש
הוא יפעל כראוי כאשר ניתנים שמות חלופיים לספריות (כל עוד
הם מופיעים לפני סימן האחוז). לדוגמה,

$(filesubst ./src/%.c, %.o, $(wildcard src/*.c))

יעבוד עם filesubst אבל לא עם patsubst.

filter_out_dirs שמות קבצים
מחזירה את כל שמות הקבצים שאינם מפנים לתיקיות.

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

TCL_INCLUDE := -I$(dir_noslash $(findfile tcl.h,
/usr/local/stow/tcl-8.4.5-nothread/include
/usr/include/tcl8.4 /usr/include/tcl
/net/na1/tcl8.4a3/include /net/na1/tcl8.4a3/include))

זה מאתר את הקובץ tcl.h על ידי חיפוש בכל הספריות הנ"ל. המוחלט
מוחזר נתיב לקובץ. לאחר מכן, "$(dir_noslash)" מחלץ את הספרייה הזו, והוא
מוכנס לנתיב include.

מצא_תוכנית שם
החזר את התוכנית הראשונה ברשימה שניתן למצוא ב-PATH. זה שימושי
כאשר ישנן מספר תוכניות מקבילות שניתן להשתמש בהן, ואתה רק רוצה
בחר אחד מהם. לדוגמה, הנה הגדרת ברירת המחדל של כמה אפשרויות נפוצות
משתנים ש-makepp מספק אם לא תכניסו אחד ל-makefile שלכם:

CC = $(find_program gcc egcc pgcc c89 cc) # ועוד, תלוי במכונה
F77 = $(מצא_תוכנית f77 g77 fort77)
CXX = $(find_program g++ c++ pg++ cxx CC aCC)

אם אף אחת מהתוכניות לא נמצאה, הפונקציה "$(find_program)" מחזירה את המחרוזת not-found, ו-
רושם את מה שלא נמצא. זה בדרך כלל לא יביא ליצירת makefile פונקציונלי, אבל זה
נוטים להניב הודעות שגיאה טובות יותר. לדוגמה, אם תעשה משהו כמו
זֶה:

%.o : %.c
$(CC) $(קלטים) -o $(פלטים)

ו-makepp לא מוצא מהדר C ברשימה למעלה, הוא יחליף את ה-not-found.
אחרת המעטפת תנסה להריץ את קובץ המקור ותגרום לשגיאה שתתקבל
ההודעה עלולה להיות ממש מוזרה.

מצא_כלפי מעלה שם הקובץ
מחפש קובץ בשם הנתון בתיקייה ., .., ../ .., ../../.., וכו ',
עד למציאת הקובץ או עד להגעה לספריית השורש או עד לאיתור הספרייה
במערכת קבצים שונה. (דרישה אחרונה זו נועדה למנוע בעיות עם
(אוטומאטרים או מערכות קבצים רשת תקועות.) אם יש לך RootMakeppfile, גם זה
מחסום המונע חיפוש גבוה יותר.

לדוגמה, אם יש לך פרויקט עם רמות רבות של תיקיות משנה, אתה יכול
כלול את הפרגמנט המשותף הזה בכל קבצי ה-makefile (למשל, באמצעות הפונקציה "include"
הַצהָרָה):

TOP_LEVEL_INCLUDE_DIR := $(find_upwards כולל)
# מחפש ספרייה המכילה את
# כולל תיקיית משנה.

%.o : %.c
$(CC) $(CFLAGS) -I$(TOP_LEVEL_INCLUDE_DIR) -c $(קלט) -o $(פלט)

בעיה נוספת ש-"find_upwards" יכול לעזור לפתור היא איתור הספרייה ברמה העליונה
של מבנה. לעתים קרובות כדאי להגדיר משתנה כך:

למעלה := ../../..

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

למעלה := $(dir_noslash $(find_upwards רישיון))

"$(find_upwards LICENSE)" מחזירה את הנתיב המלא של קובץ הרישיון;
הפקודה "$(dir_noslash ...)" מסירה את שם הקובץ ומחזירה רק את הספרייה.

(שימו לב שההצהרה "include" מחפשת אוטומטית קבצים כלפי מעלה, כך שיש
אין צורך לעשות דבר כזה:

כלול את $(find_upwards top_level_rules.mk)

במקום זאת, אתה יכול פשוט לעשות

כלול את top_level_rules.mk

וזה יעבוד באותה מידה.)

אם הקובץ לא יימצא, הפקודה "find_upwards" תבטל את הבנייה עם הודעת שגיאה.

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

$(מצא_כלפי מעלה קובץ1 קובץ2)

שווה

$(מצא_כל_מעלה קובץ1) $(מצא_כל_מעלה קובץ2)

אם ברצונך לחפש אחד מהקבצים, השתמש במקום זאת ב-"find_first_upwards".

מצא_ראשון_מעלה file1 file2 ...
פונקציה זו מתנהגת כמו "find_upwards" אלא שהיא מחזירה את הקובץ הראשון של כל קובץ
קבצים ברשימה שהוא מוצא. באופן ספציפי, הוא בודק את הספרייה הנוכחית עבור
כל אחד מהקבצים ברשימה, ומחזירה את הקובץ הראשון שקיים או שניתן לבנות אותו.
אם אף אחד מהקבצים לא קיים או לא ניתן לבנות אותו בספרייה זו, הוא בודק .., לאחר מכן
../ ..וכו', עד שהוא מגיע לספריית השורש או לספרייה שהיא
ממוקם במערכת קבצים שונה.

זמין_first_available file1 file2 ...
החזרת הקובץ הראשון ברשימה שקיימת או שניתן לבנות אותה. זה יכול להיות שימושי עבור
התאמת ה-makefiles שלך לעבודה על מספר מכונות או רשתות שונות, היכן
קבצים חשובים עשויים להיות ממוקמים במקומות שונים. לדוגמה, הנה שורה מ
אחד מקבצי ה-makefile שלי:

TCL_LIB = $(first_available
/usr/local/stow/tcl-8.4.5-nothread/lib/libtcl8.4.so
/usr/lib/libtcl8.4.so /usr/lib/libtcl.so
/net/na1/tcl8.4a3/lib/libcl8.4.a
/net/na1/tcl8.4a3/lib/libtcl8.4.sl)

שורה זו תבדוק את ספריית Tcl בכל המקומות הנ"ל, ותעצור ב-
הראשון שהוא מוצא. פקודת הקישור כוללת לאחר מכן את $(TCL_LIB) כך שנקבל את
ספריית Tcl מתאימה.

מקשר_להסיק file1 file2 ...
בהינתן רשימה של קבצי אובייקט, ראשית בנה אותם אם הם עדיין לא נוצרו. לאחר מכן מצא
האם הם תלויים במקור פורטרן, C++ או C ומחזירים את הקוד המתאים
מהדר (שיודע לקשר טוב יותר מ-"ld").

אובייקטים_להסיק file1 file2 ..., דפוס
$(אובייקטים_להסיק_אובייקטים אובייקט1.o אובייקט2.o, *.o)

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

האלגוריתם של מקפ להסקת תלויות אובייקטים תלוי במוסכמה ש...
המימוש של כל המחלקות או הפונקציות המוגדרות בקובץ כותרת "xyz.h" הן
הוקמפל לקובץ אובייקט בשם "xyz.o" (או "xyz.lo"). לכן, האלגוריתם של makepp עבור
הסקת תלויות אובייקטים מתחילה עם אובייקט אחד או כמה אובייקטים שאנו יודעים שחייבים להיות
מקושר לתוכנית. זה בודק אילו קבצים נכללו עם "#include" ב
מקורות אלה, ומנסה למצוא קבצי אובייקט תואמים עבור כל אחד מה-include
קבצים.

יש לציין את "$(infer_objects)" ברשימת התלויות של תוכנית, כמו
זֶה:

myprog: $(infer_objects main.o another_object.o,
**/*.o /other/library/dirs/**/*.o)
$(CXX) $(קלטים) -o $(פלט) $(LIBS)

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

לדוגמה, נניח ש-"main.o" מגיע מ-"main.cpp", הכולל את "my_class.h".
"$(infer_objects)" מחפש קבצים בשם "my_class.o". אם בדיוק אחד כזה
קובץ שנמצא, הוא נוסף לרשימה. (אם נמצאו שני קבצי אובייקט "my_class.o"
בספריות שונות, מודפסת הודעת אזהרה.) גם "infer_objects"
בוחן את "my_class.cpp" כדי לראות מה הוא כולל, ואילו קבצי אובייקט נוספים נמצאים
מְרוּמָז.

mktemp
mktemp קידומת
mktemp קידומתXXX
טמפ' מוקדמת /
מחזיר שם קובץ זמני בלתי צפוי, שאינו קיים כרגע. אין שם
הצבעה לאותו קובץ מוחזרת פעמיים, אפילו עם נתיבים יחסיים שונים,
בתוך ריצת makepp אחת (למעט אולי עם make רקורסיבי מסורתי, או אם Perl
קוד שפועל בתוך כלל קורא לפעולה "f_mktemp"). בסוף ה-makepp מפעילים את כל
קבצים המוחזרים על ידי פונקציה זו נמחקים, אם הם קיימים (שוב, למעט אלה
(המוחזר על ידי פונקציה זו בקוד פרל הפועל בתוך כלל).

כל מספר של "X" באותיות גדולות בסוף הארגומנט מוחלף במספר הזה
אותיות וספרות אקראיות. ככל שיש יותר, כך פחות סביר שזה יתנגש
עם תהליכים אחרים, כך שאם נותנים קידומת כמו "/tmp/abc.", אמור להיות לך מספיק
"X". אם יש יותר מ-X אחד, התו הראשון מגיע ממזהה התהליך. אם
אין כאלה, זה כאילו היו עשרה, וזה כביכול מספיק (8.4e17
אפשרויות או 3.7e15 ב-Windows). אם אין ארגומנט, הקידומת מוגדרת כברירת מחדל ל-
"זמן"בתיקייה הנוכחית.

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

כמו כן, מכיוון שזה תמיד שונה, עליך להשתמש בזה בפעולת כלל רק אם אתה משתמש
":build_check ignore_action":

TMPFILE ;= $(mktemp) # קריאה אחת; "=" פירושו 1 קריאות: 3 קבצים
ספירה א' ספירה ב': :build_check ignore_action
יוצר-As-ו-Bs >$(TMPFILE)
&grep -c /A/ $(TMPFILE) -o A-count
&grep -c /B/ $(TMPFILE) -o B-count

או שאתה צריך לייצא אותו ולתת ל-Shell להעריך אותו:

ייצוא קובץ TMP; = $(mktemp)
ספירה א' ספירה ב':
produce-As-and-Bs >$$TMPFILE # makepp לא רואה את ערך ה-var
fgrep -c A $$TMPFILE >A-count
fgrep -c B $$TMPFILE >B-count

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

%.x: %.y
&grep foo $(קלט) -o $(mktemp)
&sed bar $(mktemp /) -o $(output) # פעולה על הפלט של &grep

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

נוצר_רק שמות קבצים
מחזירה רק את שמות הקבצים ברשימה שנוצרו על ידי makepp ולא מאז
שונה, בהתאם לקובץ מידע הבנייה.

פונקציה זו שימושית בכללי יעד נקיים (אם כי כמובן ש-"makeppclean" הוא ה-
גרסה מועדפת):

$(נקי מזויף):
&rm -f $(נוצר_רק_**)

רק_לא_מטרות שמות קבצים
מחזירה רק את שמות הקבצים ברשימה שאינם יעדים של כלל כלשהו (או
כללים מפורשים או כללים של תבנית). ניתן לציין תו כללי (ראה את "$(wildcard)"
פונקציה לפרטים נוספים על תווים כלליים של makepp). ניתן להשתמש בפונקציה זו ליצירת
יעד הפצה, לדוגמה:

.PHONY: הפצה

הפצה:
&mkdir our_product-$(VERSION)
&cp $(filter-out %~, $(only_nontargets *)) our_product-$(VERSION)
tar cf - our_product-$(VERSION) | gzip -9c > our_product-$(VERSION).tar.gz

במקרה זה, הפונקציה "$(only_nontargets *)" מחזירה כל קובץ בספרייה הנוכחית.
שאינו יעד של כלל כלשהו. ה-"$(filter_out %~, ...)" מסיר את העורך
גיבויים.

בדומה ל-"only_targets" (ראה לעיל), "only_nontargets" יודע רק על מטרות ש
כבר הוגדרו. זוהי בעיה רק ​​אם משתמשים בהם כדי להגדיר משתנים
עם ההקצאה ":="; אם אתה משתמש בה ברשימת התלויות או בגוף של
כלל, כל שאר הכללים כבר נראו.

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

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

$(הוצאה מזויפת):
&rm -f $(רק_ישן **/*)

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

מטרות_בלבד שמות קבצים
מחזירה רק את שמות הקבצים ברשימה שהם למעשה יעדים של כלל כלשהו
(כללי מפורשים או כללים של תבנית). ניתן לציין תווים כלליים כלליים (כולל makepp's)
תו כללי מיוחד, "**") בשמות הקבצים. (ראה את הפונקציה "$(wildcard)" למידע נוסף
פרטים. ניתן להשתמש בזה עבור מטרה נקייה, לדוגמה:

.PHONY: נקי

לְנַקוֹת:
&rm -f $(רק_מטרות *)

עכשיו אם תקלידו "makepp clean", זה ימחק כל מה שהוא יודע איך לבנות.
אל תיצרו יעד נקי, השתמשו ב-"makeppclean" במקום זאת!

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

mylib.a: *.o
&rm -f $(פלט)
$(AR) cr $(פלט) $(קלטים)

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

mylib.a: $(only_targets *.o)
&rm -f $(פלט)
$(AR) cr $(פלט) $(קלטים)

אז הבעיה הזו לא תתרחש.

שימו לב שזה מתייחס רק לקבצים שידועים כיעדים at מה היא זמן אתה
לעורר "רק-מטרות". אם "רק_מטרות" מופיע בתלות או בפעולות של
כלל, אז כל היעדים האפשריים יהיו ידועים מכיוון שתלות ופעולות אינן
מוערך עד שהכלל מבוצע. עם זאת, אם אתה מעריך, נסה להעריך אותו
מוקדם יותר ב-makefile עם משתנה ":=" כמו זה:

ALL_TARGETS := $(רק_מטרות *)

יעד 1: תלות 1
פעולות

יעד 2: תלות 2
פעולות

אז "only_targets" לא יידע על הכללים הבאים.

באופן דומה, "only_targets" לא יודע על מטרות שנוצרו בקובצי makefile שהם
טעון עם make רקורסיבי. (אבל בכל מקרה לא כדאי להשתמש ב-make רקורסיבי; השתמש
השתמשו במשפט "load_makefile", או בטעינת makefile מרומזת במקום זאת.)

relative_filename file1 file2 קובץ3[, לַחתוֹך]
מחזירה את שם הקבצים הללו ביחס לתיקייה הנוכחית (זו ש
(makefile נמצא בפנים). ניתן להשתמש בזה גם כדי לנקות "./" מיותרים וזבל אחר מ
הנתיב:

DIR := .
תת-ספרייה := ..
FNAME := $(DIR)/../otherdir/$(SUBDIR)/files
X := $(relative_filename $(FNAME))

If לקצץ אם זה נכון (בדרך כלל 1) שמות הקבצים המוחזרים יכילו קו נטוי
על ידי הוספת "./" לפניו במידת הצורך, כך שתוכל להשתמש בו כשם קובץ הרצה מבלי
לדאוג לגבי נתיב חיפוש הפקודה שעוקף את מיקום הספרייה.

אם הנתיב עובר דרך ספריית השורש, ספריית האב של ספריית הבית שלך או
ה-"$(ROOT)" של מערכת הבנייה שלך, או ב-Windows root של כונן (בהתאם ל-
סביבה, זה קורה גם עבור /cygdrive/c or /c), נתיב מוחלט יהיה
חזר במקום זאת.

יחסית_ל file1 file2 קובץ3[, מַדרִיך]
מחזירה את שם הקבצים הללו ביחס לספרייה שצוינה. זהו
בדרך כלל שימושי כאשר מסיבה כלשהי עליך לבצע פקודה מ-
ספרייה שונה (ספריית ברירת המחדל הנוכחית):

source_backup.tar:
cd .. && tar cf $(relative_to $(output), ..) $(relative_to ., ..)

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

לדוגמה,

$(סיומת src/foo.c src-1.0/bar.c hacks)

מייצר את התוצאה ".c .c".

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

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

Makepp תומך בכל תווי הפגז הרגילים ("*", "?" ו-"[]"). יש לו גם א
תו כללי "**" שמתאים למספר כלשהו של ספריות ביניים. (רעיון זה היה
נגנב מ-zsh.) לדוגמה, "**/*.c" תואם את כל ה- .c קבצים בכל קובץ המקור
עץ. "objects/**/*.o" תואם את כל ה- .o קבצים הכלולים בכל מקום ב
ספריית משנה אובייקטים או כל אחת מתת-הספריות שלה או כל אחת מתת-הספריות שלהן. ה-
תו כללי "**" לא יעקוב אחר קישורים רכים לספריות בשום רמה, וגם לא
ניסיון להיכנס לספריות שקיימות אך לא ניתן לקרוא אותן. כמו כן, קבצים ו
ספריות שקיימות אך לא ניתן לקרוא אותן לא יוחזרו על ידי "$(wildcard)".

מחרוזת פונקציות
הוסף קידומת קידומת, מילים
מוסיף את מחרוזת הקידומת לפני כל אחת מהמילים. זה בעיקר עבור GNU make
תאימות; באמצעות הרחבה בסגנון rc, ניתן לעשות זאת בצורה קריאה יותר
ככה:

מודולים := abcd
X_OLD_STYLE := $(הוסףקידומת $(OBJDIR)/, $(הוסףסיומת .o, $(מודולים)))
X_NEW_STYLE := $(OBJDIR)/$(MODULES).o # זה לא יותר קל לקריאה?

הוספה סִיוֹמֶת, מילים
מוסיף את מחרוזת הסיומת לכל אחת מהמילים. זה בעיקר עבור GNU make
תאימות; באמצעות הרחבה בסגנון rc, ניתן לעשות זאת בצורה קריאה יותר
ככה:

X_OLD_STYLE := $(הוספת סיומת .o, $(מודולים))
X_NEW_STYLE := $(מודולים).o

שיחה מִשְׁתַנֶה[, מילים]...
הפונקציה "call" ייחודית בכך שניתן להשתמש בה כדי להתייחס משתנה בתור
פונקציה פרמטרית. ניתן להקצות ביטוי מרוכב ל משתנה ואת השימוש
"קריאה" כדי להרחיב את תוכנה לערכים שונים שנקבעו על ידי מילים מאוחר יותר. ב
מערכות make אחרות, משתנה המשמש בעיקר לצורך הרחבה באמצעות
"שיחה", נקראת מאקרו.

במהלך הרחבת המאקרו, המשתנים הזמניים $1, $2, "..." עיין ב
ארגומנטים שניתנו ל-"call" במהלך הפעלתו. המשתנה $0 יורחב ל
שם המאקרו (כלומר משתנה) ש"קריאה" זו מתרחבת כעת.

אין הגבלה על מספר הארגומנטים שניתן "לקרוא" למקרו או על מספר הארגומנטים.
פרמטרים שמקרו עשוי לצפות להם. אם תעבירו ארגומנטים נוספים ל-"call" כמאקרו
אם נחוץ, כל הארגומנטים החורגים יימחקו. אם תעביר פחות ארגומנטים מ-
macro expect, כל הפרמטרים החורגים מהם מתכווצים למחרוזת ריקה.

ראשית דוגמה פשוטה:

השאר = $(רשימת מילים 2, $(מילים $(1)),$(1))
רשימה = ABCDE
אבל קודם := $(קריאה לשאר, $(רשימה))

כאן, המשתנה "$(butfirst)" יכיל את הרשימה "BCDE".

ועכשיו לדוגמה מורכבת יותר שתראה מה אפשרי:

השאר = $(רשימת מילים 2,$(מילים $(1)),${1})
mymap = $(if $2,$(call $1,$(firstword $2)) $(call $0,$1,$(call rest,$2)))
downcase = ${makeperl lc("$1")}

UCWORDS = כל המילים האלה הן באותיות גדולות
DCWORDS := $(call mymap,downcase,$(UCWORDS))

עכשיו "$(DCWORDS)" מכיל את "כל המילים האלה הן באותיות גדולות". אגב: זה לא יוצר שום
ההבדל, האם אנו ניגשים לטיעונים דרך $1, "${1}" or "$(1)" בתוך מאקרו.

ניתן להשתמש במשתנה ישירות כאילו היה פונקציה, אם אין
פונקציה של שם זה. זה מומר באופן פנימי ל-"call", כך שאלו הם
שווה ערך:

דיון = ה-$0 הפך ל-$1 $2.
ישיר = $(דיון,ארגומנט)
נקרא = $(דיון נקרא, טיעון, ארגומנט)

ייתכן ונתון שנוי במחלוקת האם "$[call]" צריך גם להרחיב את "$[]" של המאקרו.
ביטויים, או האם פונקציה צריכה תמיד לעשות את אותו הדבר, לא משנה איך היא
נקרא. האחרון נבחר, מכיוון שעם תחביר make רגיל זה יהיה
בלתי אפשרי להכניס "$[1], $[2]..." למשתנה (הם יוחלפו בכלום,
עוד לפני שההקצאה מתבצעת.) לכן, אם יש לך מאקרו להגדרת
כלל, אתה רוצה שביטויים כמו "$(output)" יראו כאשר הכלל מנותח, כך
עליך להגן עליהם מפני "שיחה":

הגדר את הכלל שלי
2 דולר: 1 דולר
הפקודה שלי $$(קלט) -o $$(פלט)
endef
$[הכלל שליקלט,הפלט שלי]

לסנן דפוסים, מילים
מחזירה את כל המילים ברשימה שתואמות את התבניות. התבניות יכולות להיות פשוט אחרות
מילים, או תווים כלליים של שמות קבצים (למשל, "*", "?" ו-"[az]" מזוהים), או שהם עשויים
לכלול תו "%", שמשמעותו להתאים לכל מחרוזת בנקודה זו (כמו "*").

סינון_החוצה דפוסים, מילים
מחזירה את כל המילים ברשימה שאינן תואמות את התבניות. תבניות יכולות להיות פשוט
מילים אחרות, או תווים כלליים לזיהוי שמות קבצים (למשל, "*", "?" ו-"[az]" מזוהים), או
ייתכן שיש להם תו "%", שמשמעותו להתאים לכל מחרוזת בנקודה זו (כמו
"*").

לדוגמה:

libproduction.a: $(filter_out test_*, $(wildcard *.o))

ישים את כל .o קבצים שקיימים או שניתן לבנות, למעט אלו שמתחילים ב- מבחן_,
אל תוך libproduction.a.

מחרוזת חיפוש למצוא, in
לחזור למצוא, אם זוהי תת-מחרוזת של in.

מילה ראשונה מילים
החזר את המילה הראשונה.

מַפָּה מילים, perlcode
makemap מילים, perlcode
בדומה למפה של פרל, חל perlcode לכל מילה בתורה ומחזירה את
תוצאות. הגרסה הראשונה היא קוד פרל רגיל, בעוד שהגרסה השנייה עוברת תחילה
קוד הפרל באמצעות הרחבת משתנים בסגנון Make. המילים מורחבות בשניהם
במקרים.

המילים הן ב-$_ והן מוחזרות אלא אם כן אינך מגדיר $_. זה מיועד עבור
שינויים שלא מטופלים בקלות על ידי "patsubst". רק הפסיק הראשון משמש כמפריד,
כל האחרים נחשבים חלק מ perlcode.

# החלפת מילים. שימוש כפול בסוגריים, כדי לאפשר סוגריים בפרלקוד, או שימוש ב-${}:
X = $((מפה $(VALUES), s/(.+)-(.+)/$2-$1/))
# ניתן להשתמש בביטויי make, אך לאחר מכן עליכם להשתמש ב-$$ עבור Perl $:
Y = $(makemap $(VALUES), tr/$(OLDCHARS)/$(NEWCHARS)/ או $$_ = 'נכשל')
# ניתן לפסול מועמדים:
Y = $(מפה $(ערכים), undef $_ אם /לא_טוב/)

להצטרף מילים1, מילים2
בצע חיבור זוגי של המילים הראשונות והמילה השנייה.

פטסובסט תבנית, תַחֲלִיף, מילים
מבצע החלפה על כל מילה ברשימת המילים. התו "%" מתאים לכל מילה
מחרוזת. ניתן להמחיש זאת בצורה הטובה ביותר באמצעות דוגמה:

OBJS = $(patsubst %.c, object_dir/%.o, $(C_SOURCES))

לוקח כל קובץ ב-C_SOURCES ומחזיר את שם קובץ האובייקט ב-object_dir.
לפעמים זה תמציתי יותר להשתמש בהפניה להחלפה, למשל, האמור לעיל יכול להיות
נכתבו כ

OBJS = $(C_SOURCES:%.c=תיקיית_אובייקטים/%.o)

sort word1 word2 word3 ...
ממיין את המילים לפי סדר לקסיקלי ומסיר כפילויות.

להפשיט מחרוזת
מסיר רווחים לבנים מובילים וסופיים ממחרוזת ומחליף כל רווח פנימי
רצף של תו רווח לבן אחד או יותר עם רווח בודד. לכן, "$(strip ab
ג)" גורם ל-"abc".

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

רגליים ברחוב (subst ee, EE, רגליים ברחוב)

מחליף את המחרוזת "רגליים ברחוב".

מילה טקסט
מחזירה את nהמילה של טֶקסטהערכים הלגיטימיים של n להתחיל מ-1 בהתחלה
או אחורה מ-1- בסוף. אם n גדול יותר ממספר המילים ב טֶקסט, ה
הערך ריק.

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

מילים טֶקסט
מחזירה את מספר המילים ב טֶקסט.

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

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

תיקיות := abcd
קבצים := $(foreach dir,$(dirs),$(wildcard $(dir)/*))

כאן הטקסט הוא "$(wildcard $(dir)/*)". החזרה הראשונה מוצאת את הערך "a" עבור dir,
כך שזה מייצר את אותה התוצאה כמו "$(wildcard a/*)"; החזרה השנייה מייצרת
התוצאה של "$(wildcard b/*)"; והשלישית, זו של "$(wildcard c/*)".

לדוגמה זו יש את אותה התוצאה (למעט הגדרת "dirs") כמו לדוגמה הבאה:

קבצים := $(תו כללי a/* b/* c/* d/*)

כאשר טקסט מסובך, ניתן לשפר את הקריאות על ידי מתן שם, עם
משתנה נוסף:

find_files = $(wildcard $(dir)/*)
תיקיות := abcd
קבצים := $(foreach dir,$(dirs),$(find_files))

כאן אנו משתמשים במשתנה find_files בדרך זו. אנו משתמשים ב-"=" פשוט כדי להגדיר
משתנה המתרחב באופן רקורסיבי, כך שערכו מכיל קריאה לפונקציה בפועל אל
יורחבו מחדש תחת שליטה של ​​foreach; משתנה מורחב בפשטות לא יעבוד,
מכיוון ש-wildcard ייקרא פעם אחת בלבד בעת הגדרת find_files.

הערה: אין לבלבל זאת עם המשתנה המיוחד "$(foreach)".

מידע טֶקסט
אזהרה טֶקסט
שגיאה טֶקסט
פלט טקסט שמחזיר את ה"כלום". הראשון עובר ל-STDOUT, השני ל-STDERR,
השלישי גם מבטל את העיבוד.

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

רשימת_קבצים:
# פקודות מעטפת לחישוב רשימת קבצים להכנסה לתוכנית

my_program : $(&cat $(רשימת קבצים מוקדמת))

אם אתם צריכים את הרשימה ביותר מכלל אחד, יהיה יעיל יותר להשתמש ב-
הרחב לכל היותר משתנה אחד:

רשימת_קבצים ;= $(&cat $(רשימת_קבצים שנבנתה מראש))

my_program1 : ao $(רשימת_קבצים)

my_program2 : bo $(רשימת_קבצים)

אם במקום זאת ציינת רק "$(&cat file_list)", אז makepp לא יכפה
file_list יהיה מעודכן לפני ביצוע פקודת המעטפת. שימוש ב-"$(prebuild)"
זוהי הדרך הטובה ביותר לפתור את הבעיה הזו. ייתכן שתתפתה לנסות דברים אחרים, כמו
זֶה:

my_program : רשימת_קבצים $(&קטגוריית רשימת_קבצים)

אבל זה לא יעבוד מכיוון ש-"$(&cat file_list)" מוערך לפני ש-makepp מנסה לעשות זאת.
בנה "רשימת_קבצים".

מטרות_מזויפות_בלבד שמות
מחזירה רק את השמות ברשימה שהם מטרות מזויפות של כלל כלשהו (או
כללים מפורשים או כללים של תבנית). ניתן לציין תווים כלליים כלליים (כולל תווים מיוחדים של makepp)
תו כללי, "**") בשמות הקבצים. (ראה את הפונקציה "$(wildcard)" לפרטים נוספים.
ניתן להשתמש בזה לקיבוץ מטרות, לדוגמה:

$(בדיקות מזויפות): $(only_phony_targets */**/tests)

מקור משתנה
שם המשתנה, מציין מהיכן מגיע ערכו.

פרל perlcode
makeperl perlcode
מעריכה את קוד ה-perl בבלוק ומחזירה את התוצאה. הגרסה הראשונה היא Perl רגילה
קוד, בעוד שהגרסה השנייה מעבירה תחילה את קוד ה-perl דרך משתנה Make-style
הַרחָבָה.

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

VAR = 1
VAR1 = ${perl ($VAR + 1) * 3}
VAR2 = $(perl do { $VAR *= 3; החזר $VAR + 1 } אם $VAR)
VAR3 = $(makeperl $(VAR1) * 3 + $$VAR) # אחד Make var ואחד Perl var
VAR = $((perl if( ... ) { ... }))

מְזוּיָף מילים
מציין שרשימת המילים היא למעשה מטרות מזויפות, ומחזיר את רשימת המילים
מטרות. זה מיועד לשימוש כך:

$(הכל מזויף): my_program

$(נקי מזויף):
&rm -f *.o התוכנית שלי

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

.PHONY: הכל נקי

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

XYZ := $(הדפס $(patsubst %.c, %o, $(קבצי_מקור)))

ידפיס את תוצאת הקריאה "patsubst".

XYZ := $(patsubst %.c, %o, $(print $(SOURCE_FILES)))

ידפיס את הארגומנט האחרון לקריאה "patsubst".

פָּגָז פקודת מעטפת
מחזירה את הפלט מפקודת המעטפת הנתונה, כאשר שורות חדשות מוחלפות ברווחים.

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

תאריך = $(תאריך מעטפת) # טוב יותר: $(זמן מקומי סקלר של פרל)
VAR = ${{shell f() { echo hello; }; f}}

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

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

$(נקי מזויף):
$(xargs $(RM), $(only_targets **/*))

יש לכך גם את תופעת הלוואי שלא נוצרת פקודה כלל אם הרשימה
במקרה ריק. אבל במקרה הזה עדיף להשתמש ב-&rm המובנה,
מכיוון שהארגומנטים לפקודות המובנות מוגבלים רק על ידי הזיכרון של פרל:

$(נקי מזויף):
&rm -f $(רק_מטרות **/*)

אם מצוין ארגומנט שלישי, הוא משמש לתיקון מאוחר של כל פקודה. זהו
שימושי לציון מפנים מחדש, למשל (אם כי גם כאן &echo יעזור):

לְהַפְגִין:
&rm -f $@
&גע ב-$@
$(xargs echo, $(only_nontargets **/*), >> $@)

חלק מהתיעוד הזה מבוסס על תיעוד ה-make של GNU.

שימו לב שאם פונקציה נקראת במהלך אתחול makefile, לדוגמה
הרחבת משתני ייצוא, הודעות שגיאה או אזהרה ידווחו על שורה מספר 0.

השתמש ב-makepp_functions באופן מקוון באמצעות שירותי onworks.net



התוכניות המקוונות האחרונות של לינוקס ו-Windows