הבנת תחביר Makefile: בעיות ופתרונות נפוצים (כולל 'מפעיל חסר' ו'נקודת כניסה לא נמצאה')

Hbnt Thbyr Makefile B Ywt Wptrwnwt Npwzym Kwll Mp Yl Hsr W Nqwdt Knysh L Nmz H



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

הבנת התחביר הבסיסי של Makefile

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







מִשְׁתַנֶה s: נתונים בסיסיים המאחסנים אובייקטים הדרושים לשימוש ב-makefile. משתנים אלה משמשים לציון מהדר, דגלים, קבצי מקור, קבצי אובייקט וקובצי יעד. בתוך קובץ ה-make-לדוגמה הבא, ישנם בסך הכל חמישה משתנים שהם CXX (כדי להגדיר מהדר C++), CXXFLAGSc (דגלי מהדר), TARGET (כדי להגדיר שם קובץ יעד להפעלה), SRCS (כדי להגדיר קובץ קוד מקור) , OBJS (להכיל את קובצי האובייקט שנוצרים באמצעות קובץ קוד המקור).



יעדים: פלט צפוי לבנות מהמקור. זה יכול להיות קובץ יעד או כל שם סמלי: 'הכל' הוא יעד ברירת המחדל שאמור להיבנות באמצעות משתנה 'TARGET', '$TARGET' תלוי במשתני 'OBJS', והיעד 'נקי' מסיר את היעד ו קבצי אובייקט מספריית העבודה.



כללים ופקודות בנייה: סט של הוראות בסיסיות לביצוע כדי ליצור יעד מקובץ המקור או מתלות. לדוגמה, הכלל '%.o: %.cpp' מציג שהקובץ עם סיומת 'cpp' משמש ליצירת קובץ אובייקט עם סיומת 'o' בעוד ששני הקבצים מכילים את אותו שם. מצד שני, פקודת הבנייה $(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJS) משמש לקישור בין קובץ אובייקט וקובץ יעד חדש. באותו אופן, הפקודה build $(CXX) $(CXXFLAGS) -c $< -o $@ קומפילציה של קובץ המקור לקובץ אובייקט.





תלות: התלות תמיד יש כאשר אתה רוצה ליצור makefile. לדוגמה, היעד 'הכל' תלוי במשתנה 'TARGET' בעוד שה-'TARGET' תלוי במשתנה 'OBJS'. יחד עם זאת, המשתנה 'OBJS' תלוי בקובץ המקור באמצעות המשתנה 'SRCS'.

הערות: בדרך כלל משתמשים בהוראות המובנות לאדם כדי להסביר את מטרת שורת הקוד במקרה שאתה משתמש בקובץ לאחר זמן רב. ב-makefile הבא, אנו משתמשים בהערות המתחילות בסימן '#' כדי להסביר כל שורה.



CXX = g++
CXXFLAGS = -סטד =c++ אחד עשר -קִיר
TARGET = חדש
SRCS = main.cpp
OBJS = $ ( SRCS:.cpp=.o )
הכל: $ ( יַעַד )
$ ( יַעַד ) :$ ( OBJS )
$ ( CXX ) $ ( CXXFLAGS ) -או $ ( יַעַד ) $ ( OBJS )
% .O: % .cpp
$ ( CXX ) $ ( CXXFLAGS ) $ < -או $ @
לְנַקוֹת:
rm $ ( יַעַד ) $ ( OBJS )

בעיות נפוצות ופתרונות

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

1: לא משתמש במשתנים

שימוש במשתנים ב-makefile הוא חובה שכן הוא נדרש להגדיר את המהדרים, היעד, קבצי המקור וכו'. הבעיה הנפוצה ביותר שניתן להיתקל בה היא אי שימוש במשתנה כלשהו ב-makefile. לכן, הקפד להשתמש במשתנים החיוניים כמו CXX, CXXFLAGSc(דגלים מהדר), TARGET, SRCS ו- OBJS בקובץ makefile לדוגמה הקודם.

2: בעיית מפריד חסר

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

$ ( יַעַד ) :$ ( OBJS )
$ ( CXX ) $ ( CXXFLAGS ) -או $ ( יַעַד ) $ ( OBJS )

עם ביצוע השאילתה 'עשה', אנו מקבלים שגיאת 'מפריד חסר' בשורה 13, והקובץ מפסיק לפעול. כדי להימנע מבעיה זו, הקפד להשתמש ב-'tab' במקום ברווחים.

עשה

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

$ ( יַעַד ) :$ ( OBJS )
$ ( CXX ) $ ( CXXFLAGS ) -או $ ( יַעַד ) $ ( OBJS )

3: בעיה 'נקודת כניסה לא נמצאה'.

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

#include
מופע אינט ( ) {
char v;
std::cout << 'הזן ערך:' ;
std::cin >> ב;
std::cout << ב << std::endl;
לַחֲזוֹר 0 ;
}

עם ביצוע הוראת 'עשה' בשורת הפקודה של Windows, אנו נתקלים ב'הפניה לא מוגדרת ל'WinMain''. הסיבה לכך היא שהמהדר לא מוצא שום נקודת כניסה להתחיל להפעיל את הקובץ C++. כדי לפתור זאת, החלף את 'הצג' ב'ראשי'.

4: שימוש בהרחבות שגויות

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

CXX := g++
CXXFLAGS := -סטד =c++ אחד עשר -קִיר
TARGET = חדש
SRCS = main.c
OBJS = $ ( SRCS:.cpp=.o )
הכל: $ ( יַעַד )
$ ( יַעַד ) :$ ( OBJS )

הפעלת הוראת ה-'make' מובילה אותנו לשגיאה 'אין כלל ליצירת יעד 'main.c''. כדי למנוע בעיה זו, הקפד להשתמש בסיומת קובץ המקור הנכונה.

עשה

5: תלות חסרות

בזמן כתיבת makefile, עליך לכלול את כל התלות של קובץ מקור כדי לקבל את הפלט הרצוי. לדוגמה, קובץ הקוד C++ שלנו משתמש בקובץ 'myheader.h' בתור התלות שלו. לכן, אנו מזכירים זאת בקובץ הקוד C++ באופן הבא:

#include
#include 'myheader.h'
מופע אינט ( ) {
char v;
std::cout << 'הזן ערך:' ;
std::cin >> ב;
std::cout << ב << std::endl;
לַחֲזוֹר 0 ;
}

בתוך ה-makefile, אנו מתעלמים בכוונה מהשימוש בקובץ 'myheader.h' בתוך כלל הבנייה שנכתב בשורה 9.

% .O: % .cpp
$ ( CXX ) $ ( CXXFLAGS ) $ < -או $ @

כעת, תוך כדי שימוש בהוראה 'עשה', אנו נתקלים בשגיאה 'אין מה לעשות עבור 'הכל''.

עשה

% .O: % .cpp myheader.h
$ ( CXX ) $ ( CXXFLAGS ) $ < -או $ @

כדי להימנע מהבעיה האמורה ולהפעיל את קוד המקור בהצלחה, ציין את שם הקובץ 'myheader.h' בשורה התשיעית של קובץ ה-make כפי שמתואר להלן:

סיכום

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