دستور make و فایل MakeFile

در لینوکس (و دیگر سیستم عامل های شبه یونیکس) از کامپایلر gcc برای کامپایل کدهای سی استفاده می شود. خروجی یک برنامه دودویی است که می توان آن را اجرا کنیم. اگر شما از IDE هایی مانند CodeBlocks استفاده می کنید، اینها نیز gcc برای کامپایل می گیرند.

gcc main.c -o outpu_bin_file

در کد بالا گزینه o- برای تعیین نام و مسیر فایل دودویی خروجی استفاده می شود که این فایل دودویی اجرایی از تک فایل main.c ساخته می شود. اکنون گمان کنید که برنامه شما بسیار بزرگ است و چندین و چند فایل c.  دارد. در این حالت در صورت تغییر در یک فایل، به طور معمول همه فایل ها باید از نوع کامپایل (Recompile) شوند، حتی آنهایی که تغییری در آنها داده نشده است.

اگر یک بسته کد منبع (Source Code Package) را تا کنون کامپایل کرده باشید، دیده اید که سه دستور زیر را به ترتیب اجرا کرده اید. در این میان دستور make  خودکار متوجه می شود که کدام بخش از یک فایل بزرگ نیاز به کامپایل دوباره دارد.

configure
make
sudo make install
راهنمای دستور make را با دستور man make بخوانید.

درون MakeFile  چه چیزهایی است

یک MakeFile‌ شامل یک مجموعه ازهدف ها (Targets) و  Dependencie ها و قاعده ها (Rules) است. یک هدف یا Target یک فایلی است که یا ساخته یا بروز رسانی می شود ولی می تواند یک عبارت (Directive) یا یک بر چسب باشد که توسط برنامه (دستور) make  مورد ارجاع قرار می گیرند.

یک هدف وابسته به یک مجموعه از فایل های منبع (Source File)، یا Object File یا حتی یک دسته از Target های دیگر است که این وابستگی ها به گونه فهرستی از Dependency تعریف می شوند. قاعده ها یا Rule ها دستوهای هستند که برای ساخت (Build) هدف ها توسط نیازمندی ها نیاز هستند.

زمانی که دستور  make یک MakeFile را می خواند، از روی مهرزمانی (Timestamp) متوجه می شود که کدام (فایل های) هدف (Target) باید ساخته (Build) شوند. اگر مهر زمانی تازه تر باشد، دستور make قواعد (دستورهای) متناسب با هدف را اجرا می کند.

در شکل زیر یک نمونه از برنامه ای به زبان سی نشان داده شده است که دارای سه فایل کد منبع به نام های type.h (فایل سرآیند که اعلان تابع mysum و برخی از نوع ها یا ثابت ها را شامل می شود)، فایل mysum.c  (که بدنه تعریف تابع mysum را شامل می شود) و فایل t.c  که پیوست فایل سرآیند type.h و فایل سرآیند stdio.h و بدنه تابع main  را شامل می شود.

برای کامپایل آن که دارای دو فایل کد سی به نام های mysum.c و  t.c  است دستور زیر را به کار برده ایم که در آن o- نام فایل دودویی خروجی را مشخص می کند که در اینجا آن را myt نامگذاری کرده ایم.

gcc -o myt t.c mysum.c

شکل زیر یک نمونه از makefile  را نشان می دهد که نام آن را همان نام معمول MakeFile گذاشته ام. در خط نخست نام Target  آمده است که در اینجا Target  ما همان فایل دودویی اجرایی به نام myt  است. پس از این نام علامت :  قرار گفته و سپس با یک فاصله فهرست وابستگی ها آورده شده است.

فهرست وابستگی ها همان فایل هایی هستند که برنامه متکی به آنها است که شامل سه فایل type.h و  t.c و mysum.c است. سپس در خط بعدی که حتما باید با یک TAB آغاز شود، Rule  ها نوشته می شوند که در اینجا همان دستور gcc  است.

myt: type.h t.c mysum.c                #target: dependency list
        gcc -o myt t.c mysum.c         # rules: line must begin with a TAB

اکنون اگر پیش از این فایل myt  را به کمک gcc ساخته اید، آن را پاک کنید و دستور زیر را انجام دهید. همانگونه که گفته شد، دستور make در لینوکس (و دیگر شبه یونیکس ها) فایل MakeFile را می خواند. البته هر فایلی makefile تلقی نمی شود و باید الگوی شکل نخست را داشته باشد که ساده ترین آن در سومین شکل بالا نشان داده شده است.

make -f MakeFile

در دستور بالا، جلوی گزینه f- نام فایل makefile  می آید که در اینجا من آن را MakeFile گذاشته ام ولی شما می توانید هر نام دیگری مانند mk1 را بگذارید. پس از اجرای دستور بالا، خروجی زیر نشان داده می شود.

gcc -o myt t.c mysum.c # rules: line must begin with a TAB

این خروجی همان خط دومی است که با TAB آغاز شده بود و به Rule یا در اینجا دستور کامپایل اشاره می کرد. یادآور می شوم که مزیت استفاده از makefile و دستور make در این است که دستور make با بررسی مهر زمانی، تنها آن فایل هایی را دوباره کامپایل می کند که تغییری در آن رخ داده باشد، زیرا در لینوکس زمان آخرین تغییر (Modify Time) نگهداری می شود و اگر تغییری رخ داده باشد این زمان بروز و make  از آن آگاه می شود.

اکنون اگر دوباره دستور make MakeFile را اجرا کنید می بینید که پیغام make: ‘myt’ is up to date نشان داده می شود که بدین معنی است که هیچ تغییری در کدهای برنامه انجام نشده است.

شبیه سازی تغییر دادن زمان آخرین تغییر (Modify Time)

در سسیتم عامل های یونیکسی دستوری به نام touch است که نام فایلی را دریافت می کند و سپس اگر آن فایل وجود نداشته باشد، آن فایل را می سازد و فیلدهای مختلفی مانند Access Time و  Modify Time را برای آن فایل تنظیم می کند.

ولی اگر فایل از قبل وجود داشته باشد، پس تنها فیلدهای مد نظر را تغییر می دهد و چون یکی از این فیلدها Modify Time  است، پس از دید دستور make یک تغییر در فایل های کد منبع رخ داده است. در اینجا برای نمونه دستور زیر را انجام دهید.

touch type.h

با این کار Modify Time فایل type.h  تغییر کرده، پس در اجرای دوباره دستور make -f MakeFile تنها همین فایل است که از نو کامپایل می شود. توجه کنید باز کردن و تغییر در یک فایل با هر ویرایشگری، نتیجه اش بروز شدن Modify Time است.

منبع

برای فراگیری بیشتر می توانید به سایت زیر نگاهی بیاندازید

http://sysadmingeeks.ir

https://dataset-academy.com

و یا می توانید در کانال تلگرام عضو شوید.

https://t.me/datasetacademydotcom