Make

در توسعه نرم‌افزار، make ابزاری برای ساختن اتوماتیک فایلهای اجرایی از کد منبع است. فایلی که Makefile خوانده می‌شود روند کامپایل قطعات پروژه را بر اساس پیش‌نیازهای آن معلوم می‌کند. اگر چه ابزارهای بسیار زیادی برای توسعه مداوم و اجرا کردن تست‌ها در محیط‌های برنامه‌نویسی موجود است، اما MakeFile بصورت گسترده و مخصوصا در سیستم‌های مبتنی بر یونیکس استفاده می‌شود.
مقدمه
قوی‌ترین ابزار برنامه‌نویسان برای جلوگیری از پیچیدگی‌های بیش از حد در پروژه‌ها استفاده از روش برنامه‌نویسی ماژولار ( Modular ) است.
در این روش بخش‌های مختلف پروژه بصورت ماژولهای مجزا قابل کامپایل هستند؛ ولی از طرفی هم عملیات کامپایل تک‌تک ماژول‌ها و چسباندن نهایی آن‌ها به یکدیگر، فرایندی زمان‌بر و پراشتباه است.
خوشبختانه ابزار Make برای تسهیل این مراحل و خودکارسازی این فرایند ساخته شده‌است. روند کامپایل این ماژول‌ها در فایلی به‌نام Makefile تعریف می‌شوند.
در یک نگاه کلی، make فقط برای کامپایل برنامه‌ها استفاده نمی‌شود. شما می‌توانید در هر کاری که در آن نیاز به بروزرسانی بعضی فایل‌ها متناسب با تغییر در فایل‌های دیگر است از make استفاده کنید.
بطور مثال معمولا در یک برنامه رایانه‌ای نیاز است از کدهای منبع فایل‌های آبجکت و سپس از این فایل‌های آبجکت، فایل اجرایی ساخته شود.
وقتی شما برنامه‌ای می‌نویسید، باید برای آن یک Makefile هم درست کنید و سپس برای کامپایل و نصب آن از Make کمک می‌گیرید.
make بطور خودکار تشخیص می‌دهد چه قسمت‌هایی از یک برنامه بزرگ به چه صورت باید کامپایل شوند.
همچنین می‌توان از آن برای کامپایل برنامه‌ها به هر زبانی که نوشته شده‌اند استفاده کرد، به‌شرط آنکه کامپایلر آن زبان توانایی اجرا از طریق پوسته (Shell) را داشته‌باشد.
ابزار make بطور گسترده‌ای به‌خصوص در سیستم‌های مبتنی بر یونیکس استفاده می‌شود.
قابلیت‌های Make
Make این امکان را برای کاربر نهایی فراهم می‌کند که حتی بدون داشتن اطلاعات فنی زیاد بتواند برنامه را کامپایل و نصب کند. زیرا شما جزئیات کامپایل و نصب برنامه را در Makefile نوشته‌اید.
وقتی از بین کدهای منبع یک پروژه تعدادی از آن‌ها تغییر کند، Make بطور اتوماتیک تشخیص می‌دهد چه فایل‌هایی باید بروز شوند. این امکان زمانی مفید خواهد بود که تعداد کدهای منبع یک برنامه زیاد است و در صورت اعمال تغییرات بر روی چند تای آن‌ها نیاز به کامپایل تمامی کدهای منبع و هدر دادن زمان و منابع نیست. فقط فایل‌هایی بروز می‌شوند که بطور مستقیم یا غیرمستقیم به تغییرات داده شده ربط داشته باشند. Make از طریق آخرین زمان تغییر فایل‌ها تشخیص می‌دهد که چه قسمت‌هایی باید دوباره بروز شوند.
Make وابسته به زبان برنامه‌نویسی خاصی نیست. برای ساخت فایل‌های مورد نیاز برای اجرای برنامه، در Makefile دستوری قرار دارد که در پوسته (Shell) اجرا می‌شود. بطور مثال این دستورات می‌توانند کامپایلری را برای ایجاد فایل آبجکت، لینکر را برای تولید فایل اجرایی، ar را برای به روز کردن یک کتابخانه (Library) یا صفحه‌آرایی مستندات بوسیله TeX یا Makeinfo اجرا کنند.
Make فقط برای ساخت یک برنامه به کار نمی‌رود. می‌توان از آن برای کنترل روند نصب یا حذف یک برنامه نیز استفاده کرد.
نگاهی دقیق‌تر به Makefile
محتویات Makefile
Makefileها شامل پنج چیز مختلف‌اند. قوانین صریح ، قوانین غیرصریح ، متغیرها ، رهنمون‌ها و توضیحات .
یک قانون صریح (Explicit Rule) معلوم می‌کند چه‌وقت و چطور، فایل یا فایلها باید ساخته شوند. به فایلهایی که باید ساخته شوند هدف (Target) گفته می‌شود و ممکن است وابسته به فایل (های) دیگری باشد. همچنین دستورهایی برای ساخت فایل هدف نوشته می‌شوند.
قوانین غیرصریح (Implicit Rule) معلوم می‌کنند چه وقت و چطور باید دسته‌ای از فایلها که بر اساس نامشان دسته‌بندی شده‌اند ساخته شوند.
متغیرها برای نسبت دادن مقادیر متنی به نامی مشخص است؛ و برای رجوع به آن مقدار متنی، می‌توان از نام متغیر استفاده کرد. یک مثال نوشتن نام تمام فایلهای آبجکت مورد استفاده در برنامه درون یک متغیر با نام objects است. (برای رجوع ساده‌تر)
رهنمون‌ها فرامینی هستند برای اجرای کارهای خاص که در هنگام پردازش Makefile مورد استفاده قرار می‌گیرند. مانند:
-- خواندن محتویات Makefile دیگری در دل یک Makefile.
-- تصمیم‌گیری (بر اساس مقدار درون یک متغیر) برای پردازش کردن یا نکردن قسمتی از Makefile.
-- مقدار دهی به متغیرها از طریق متنی که شامل چندین خط است.
با نوشتن کارکتر # می‌توان توضیحاتی در Makefile نوشت که عملا پردازش نمی‌شوند و فقط برای خواناتر شدن Makefile برای انسان خواهند شد.
Ruleها
Ruleها در Makefile مشخص می‌کنند که برای ساخت یک Target چه دستورهایی باید اجرا شود. همچنین می‌توان برای ساخت هدف، فهرستی از پیش‌نیازها (Dependencies) را نیز تعریف کرد. در این فهرست باید تمام فایل‌های مورد نیاز (کدمنبع یا هر نوع فایل دیگری) که برای ساخت هدف مورد نیاز است تعریف شود.
Comments use the hash symbol
target: dependencies
command 1
command 2
command n
معمولا Target نام فایلی است که قرار است توسط یک برنامه ایجاد شود. مثلا فایل‌های آبجکت یا اجرایی. همچنین می‌تواند نام کاری باشد که قرار است اجرا شود. مثل تمیز کردن یک پروژه (Clean)
پیش‌نیازها (Dependencies) فایل‌های ورودی‌ای هستند که برای ساختن هدف مورد نیازند که به هر تعدادی می‌توانند باشند.
در صورت تغییر در هر یک از این پیش‌نیازها، هدف باید دوباره ساخته شود.
البته هدف‌هایی هم هستند که نیاز به پیش‌نیازی ندارند. بطور مثال هدفی مانند Clean که باید بعضی از فایل‌ها را پاک کند.
فرمان‌های (Command) هم کارهایی هستند که Make برای ساخت هدف انجام خواهد داد. برای ساخت یک هدف ممکن است چندین دستور نیاز باشد که باید در خطوط جداگانه نوشته شوند.
توجه کنید که حتما باید در ابتدای دستورات یک کارکتر تب (TAB) قرار دهید.
متغیرها کارها را ساده می‌کنند
مثال زیر را در نظر بگیرید:
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
چنین قواعدی در Makefile، به‌شدت مستعد خطا هستند. اگر نیاز به اضافه کردن فایل آبجکت جدیدی به پروژه باشد، ما باید در تمام مکان‌های مورد نیاز آنرا اضافه کنیم.
می‌توان بوسیله متغیرها این کار را ساده‌تر و مطمئن‌تر انجام داد.
متغیرها این امکان را می‌دهند تا بتوانیم متنی را در آن‌ها ذخیره کنیم و در چندین مکان مورد استفاده قرار دهیم.
تقریبا تمام Makefileها متغیری با نامی شبیه به objects , OBJECTS , objs , OBJS , obj یا OBJ دارند که فهرستی از نام تمام آبجکت‌های مورد نیاز در پروژه را در خود نگه داشته‌است.
ما می‌توانیم برای مثال خود متغیری بنام objects را با نوشتن چنین خطی در Makefile تعریف کنیم:
objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.o
از این به بعد هر کجا نیاز به نوشتن فهرستی از فایل‌های آبکجت مورد استفاده بود، می‌توان از متغیر تعریف شده بصورت (objects)$ استفاده کرد.
edit : $(objects)
cc -o edit $(objects)
Makefile چطور پردازش می‌شود؟
بطور پیش‌فرض، Make با اولین Target موجود در Makefile شروع می‌کند (اولین هدفی که با نقطه شروع نشده است). این هدف Default Goal نامیده می‌شود. (می‌توان این هدف پیش‌فرض را توسط خط فرمان تغییر داد)
وقتی شما دستور make را در خط فرمان می‌نویسید، برنامه Make در دایرکتوری فعلی‌ای که در آن قرار دارید فایلی به‌نام Makefile را می‌خواند و شروع به پردازش اولین هدف موجود در آن می‌کند (Default Goal). اما قبل از اینکه دستورات موجود در این هدف اجرا شوند، Make باید تمام پیش‌نیازهای مربوط به آن هدف را پردازش کند. هر یک از این پیش‌نیازها نیز برای خود Rule دارند که برای ساخت آن‌ها پردازش خواهد شد.
بطور مثال در یک برنامه کامپایل دوباره یک فایل آبجکت زمانی اتفاق می‌افتد که فایل سورس یا هیدر مربوط به آن بعد از ساخت فایل آبجکت تغییر کرده باشند یا اساسا فایل آبجکت هنوز ساخته نشده‌باشد.
به این ترتیب است که قواعد (Rules) دیگر موجود در Makefile پردازش و اجرا می‌شوند. زیرا آن‌ها پیش‌نیازهای ساخت هدف اصلی هستند.
روشن است که اگر یک قاعده جزء پیش‌نیازهای هدف اصلی نباشد پردازش نخواهد شد. مگر اینکه بطور صریح از Make بخواهید آن را پردازش کند (مثلا با دستور make target-name )