لینک کوتاه مطلب : https://hsgar.com/?p=3091

چگونه با استفاده از make برنامه را کامپایل و اجرا کنیم

هر برنامه‌ای که به هر زبانی که نوشتید باید ابتدا توسط کامپایلر کامپایل شود و سپس اجراش کنید. کامپایل یعنی اینکه برنامه‌ شما به صورت ۰ و ۱ آماده می‌شود و ماشین آن را فهم می‌کند ولی هنوز اجرا نشده است و شما نمی‌توانید باهاش کار کنید. برای اجرا شدن باید فایلی که کامپایل شده را run کنید.

خودم زمانی به طور کامل تفاوت این دو را فهمیدم ولی الان یادم رفته است و حوصله دوباره خواندن آن‌ها را ندارم. خوب بریم سراغ اینکه چطور برنامه را کامپایل و اجرا کنیم. برای کامپایل به یک کامپایلر نیاز داریم. هر زبانی کامپایلر مخصوص خودش را دارد، برای مثال برای اجرای برنامه‌های به زبان سی باید کامپایلر زبان سی روی سیستم ما نصب باشد. این کامپایلر زبان سی با استفاده از یک سری فرایندها کد ما را پس از عملیات ترجمه به زبان اسمبلی و ماشین آماده اجرا می‌کند.

برای کامپایل می‌توانید برنامه‌های خاصی را دانلود کنید ولی من کامپایلر gcc را دانلود کردم و روی سیستم من که arch لینوکس نصب است. برای اجرا کافی است از دستور gcc در ترمینال استفاده کنم.

خوب این دستور gcc خودش یک سری نحو دارد که در اینجا قصد ندارم بدان بپردازم. به طور کل شما در ترمینال با فرمان زیر می‌توانید یک فایلی که به زبان سی نوشتید را کامپایل کنید.

gcc [options] [source files] [object files] [-o output file]

gcc main.c -o outpu_bin_file

اگر بروید به پوشه‌ای که در آن فایل برنامه‌تان را ذخیره کردید می‌بینید که یک فایل دیگری هم ایجاد شده است به نام outpu_bin_file.o که این می‌شود فایل اجرای شما. شما باید در ترمینال این فایل را به شکل زیر اجرا کنید تا برنامه شما اجرا شود.

./outpu_bin_file

ولی در برنامه‌های واقعی شما با چندین فایل سر و کار دارید که هر کدام از این فایل‌ها باید به ترتیب خاصی اجرا شوند. علاوه بر این هر فایل سرایندهای مخصوص خودش را دارد و کلی گزینه‌های دیگر که عملا استفاده از ترمینال برای اجرای آن‌ها نه منطقی است و نه شدنی. پس چه باید کرد.

راه حل، استفاده از نرم‌افزارهای مانند GnuMake است. اگر قصد یادگیری Make را دارید بی بر و برگرد بایستی این راهنما که راهنمای اصلی است و به زبان بسیار بسیار ساده نوشته شده است حداقل سه بار بخوانید. حالا شاید بپرسید که آیا من واقعا سه بار خواندم، راستش نه من هنوز نخواندم ولی خوب قصد دارم بخوانم.

خوب پس برای اجرا باید یک فایل Makefile بنوسید و بگویید که برنامه شما چطور باید اجرا شود.

حالا چطور باید در Makefile بنوسیم برای این کار باید یک فایل متنی به اسم Makefile بسازید. و از قاعده زیر برای نوشتن چگونگی کامپایل برنامه‌تان استفاده کنید

target … : prerequisitesrecipe
        …
        …

خوب این ترگت و پریرکویست و رسپی باید باهاشان سر و کله بزنید.

نام فایل تولید شده توسط برنامه و کلا کاری که می‌خواهیم انجام دهیم بهش می‌گویند ترگت.

پریرکویست‌‌ها فایل‌های ورودی برای ترگت هستند. هر ترگت معمولا چند تا پریرکویست‌ دارد.

رسپی دستور العمل چگونگی ایجاد ترگت با استفاده از پریرکویست‌ها است. نکته‌ای که باید بهش توجه کنید این است که باید قبل از رسپی یک تَب بزنید.

برویم بررسی کنیم یک وضعیت تقریبا ساده: فرض کنید و اگر می‌خواهید خیال کنید که هشت تا فایل سورس به زبان سی و سه تا فایل هدر دارید. همه فایل‌های سورس فایل defs.h را انکلود می‌کنند. اما command.h را فایل‌های سورس مرتبط با نوشتن و buffer.h فایل‌های سورس مرتبط با بافرینگ انکلود می‌کنند. برای ساختن یک فایل اجرایی از چنین فایل‌هایی دست به دامن make می‌شویم، نام این فایل اجرایی را edit می‌گذاریم. خوب برای این کار یک Makefile به شکل زیر می‌نویسیم:

edit : main.o kbd.o command.o display.o \
       insert.o search.o files.o utils.o
        cc -o edit main.o kbd.o command.o display.o \
                   insert.o search.o files.o utils.o

main.o : main.c defs.h
        cc -c main.c
kbd.o : kbd.c defs.h command.h
        cc -c kbd.c
command.o : command.c defs.h command.h
        cc -c command.c
display.o : display.c defs.h buffer.h
        cc -c display.c
insert.o : insert.c defs.h buffer.h
        cc -c insert.c
search.o : search.c defs.h buffer.h
        cc -c search.c
files.o : files.c defs.h buffer.h command.h
        cc -c files.c
utils.o : utils.c defs.h
        cc -c utils.c
clean :
        rm edit main.o kbd.o command.o display.o \
           insert.o search.o files.o utils.o

خط‌های طولانی با اسلش تقسیم می‌کنیم یعنی چی یعنی اینکه ادامه یک خط را در خط بعد ادامه می‌دهیم. خوب این فایل را ذخیره می‌کنیم، ترمینال را باز کرده و make را می‌نویسیم و یک Enter خرجش می‌کنیم. خوب اگر بروید به پوشه‌، که الان نمی‌توانید بروید چون این هشت فایل در دسترس شما نیست، می‌بنید که یک فایل اجرایی به نام edit وجود دارد و اگر شما در ترمینال این فایل را اجرا کنید برنامه اجرا می‌شود.

خوب اگر پس از اجرا مقداری فایل‌هایتان را ویرایش کردید باید مجدد make را انجام بدهید ولی قبل از آن باید make clean را بزنید تا کارها دوباره از نو آغاز شود. روز از نو make از نو.

راستش حوصله توضیح دادن بیشتر ندارم خودتان این مثال را با دقت بررسی کنید . یک نکته را بدانید که در مثال بالا همه ترگت‌ها فایل‌ها هستند، اولی فایل اجرایی edit است که ما می‌خواهیمش و پیش‌نیازهایش که فایل‌های با پسوندهای .o هستند معرفی کردیم. پس قبل از اینکه رسپی برای edit‌ اجرا شود پیش‌نیازهایش باید برآورده گردد. برای مثال یکی از پیش‌نیازهایش main.o هستش اگر پایین‌تر بروید می‌بنید برای تهیه این main.o به یک سری پیش‌نیازها نیاز داریم که main.c و def.h است که در پوشه ما وجود دارند پس رسپی برای main.o اجرا می‌شود و فایل main.o تهیه می‌شود و به همین صورت برای همه پیش‌نیازهای edit کارها ترتیب داده می‌شوند. پس از آن رسپی edit اجرا می‌شود و فایل اجرایی edit در خدمت شما و در دستان شما قرار می‌گیرد.

ولی گفتیم که در مثال بالا همه ترگت‌ها فایل هستند به غیر از یکی که clean دارد و این بهش می‌گویند کار. این کار پاک کردن همه فایل‌ها برای اجرای مجدد make است. کار clean تنها در صورتی انجام می‌شود که خود شما با زبان خودتان به make بگویید که این دستور را انجام دهد و این کار میسر نمی‌شود مگر اینکه make clean را تایپ کنید.

متغیرها در make

یکی از چیزهای دیگر که دانستنش از نوشتن برنامه واجب‌تر است متغیرها هستند. متغیرها همان‌طور که از اسمش پیداست یک سری چیزها را در خودش ذخیره می‌کند و در make این چیزها اسامی فایل‌ها هستند. برای مثال می‌توانیم یک متغیر به نام object به صورت زیر تعریف کنیم:

objects = main.o kbd.o command.o display.o \
          insert.o search.o files.o utils.o

این object متغیر اسامی هر هشت فایل را در خودش دارد پس به جای نوشتن تکی تکی این اسامی کافی است نام object را ببریم تا کارمان راه بیفتد.

objects = main.o kbd.o command.o display.o \
          insert.o search.o files.o utils.o

edit : $(objects)
        cc -o edit $(objects)
main.o : main.c defs.h
        cc -c main.c
kbd.o : kbd.c defs.h command.h
        cc -c kbd.c
command.o : command.c defs.h command.h
        cc -c command.c
display.o : display.c defs.h buffer.h
        cc -c display.c
insert.o : insert.c defs.h buffer.h
        cc -c insert.c
search.o : search.c defs.h buffer.h
        cc -c search.c
files.o : files.c defs.h buffer.h command.h
        cc -c files.c
utils.o : utils.c defs.h
        cc -c utils.c
clean :
        rm edit $(objects)

تمیزتر کردن makefile

برای اینکه از شلوغی برهیم make یک سری کارهای خوب ترتیب داده که نامشان را گذاشته دستورات ضمنی. این دستورات ضمن یکی‌شان این است که اگر شما نام برای مثال main.o را بردید یعنی اینکه در پیش‌نیازها main.c را نوشتید و رسپی cc -c main.c -o main.o این را قرار دادید. پس دیگر نیازی تکرار مکررات نیست. پس فایل ما به صورت زیر در می‌آید:

objects = main.o kbd.o command.o display.o \
          insert.o search.o files.o utils.o

edit : $(objects)
        cc -o edit $(objects)

main.o : defs.h
kbd.o : defs.h command.h
command.o : defs.h command.h
display.o : defs.h buffer.h
insert.o : defs.h buffer.h
search.o : defs.h buffer.h
files.o : defs.h buffer.h command.h
utils.o : defs.h

.PHONY : clean
clean :
        rm edit $(objects)

می‌توانیم استایل را تغییر بدهیم و به شکل زیر بنویسیم که میتنی بر پریرکویست‌ها دسته‌بندی کردیم:

objects = main.o kbd.o command.o display.o \
          insert.o search.o files.o utils.o

edit : $(objects)
        cc -o edit $(objects)

$(objects) : defs.h
kbd.o command.o files.o : command.h
display.o insert.o search.o files.o : buffer.h

اگر دقت کرده باشید در بالا یک

.PHONY : clean

اضافه شده است این برای این است که به make بگوییم آقای محترم لطفا اگر هم فایلی به نام clean موجود بود شما کار خودت را بکن و clean را برای پاک کردن استفاده کن.

فصل سه این راهنما مربوط به کار با makefile ها است که می‌گوید اگر چندین makefile داشتید چه باید بکنید مثلا مشخص کنید کدام makefileها اجرا بشود یا بخش خاصی از makefile خاصی اجرا شود و امثالهم که الان بهش نمی‌پردازم چون فعلا خودم باهاش سر و کار ندارم هر وقت کارم بهش خورد همان وقت به خدمتش می‌رسم.

خوب تا اینجا به صورت ساده گفتیم که make چیست و makefile چه می‌کند باقی را می‌گذاریم به آینده.

ارسال یک پاسخ

آدرس ایمیل شما منتشر نخواهد شد.