پیشنهادهای شما برای پیاده سازی یک ایده سخت افزاری

با سلام. خیلی وقت بود وبلاگ نویسی نکرده بودم و حالا پس از مدتها اومدم که بنویسم! شاید بگید الان که فرجه امتحانات هست و بهتره برم به زندگیم برسم، ولی خب توی همین فرجه هم وقت آزاد فراوان هست.

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

توی پست های جادی چند مساله جالب به چشم میخوره، اولیش اینه «چی نداریم؟! آیا وسیله ای هست اون کار رو انجام بده؟ اگر نیست، خودم میسازمش». و دومین نکته هم «پیاده سازی ایده و تبدیل کردنش به استارتاپ و حتی تا حدی به پول رسوندنش، اونقدر ها هم که فکر میکنیم سخت نیست». و حتی شاید سومیش این باشه که «معطل نکن، شروع کن به پیاده سازی». خب، حالا بیایم ببینم که من میخوام چی کار کنم؟ جادی به من ایده داد که ایده جمع کنم برای یک محصول سخت افزاری! اما محصولی که بشه به در یک مدت زمان نه چندان کوتاهی پیاده سازیش کرد و بعد ازش به پول رسید (بر خلاف StrongPC که بیشتر فاز تحقیقی داره).

ایده هایی که در ذهن خودم هستن اینان :

  • پیاده سازی یه دستگاه ساده با استفاده از میکروکنترلرهایی که توی بازار موجودند، و روبرو شدن با چالش هایی مثل مطالعه معماری، برنامه نویسی برای ریزپردازنده، طراحی مدارهای واسط و … .
  • پیاده سازی یه دستگاه ساده با استفاده از آردوینو و ماژول هاش
  • پیاده سازی یک دستگاه ساده IoT طور با استفاده از Cubieboard یا رزبری
  • و …

حالا از شماها که این پست رو میخونید، میخوام در این باره کمک بدید. اول این که «دستگاه ساده» چی میتونه باشه (مثلا ساعت؟! تقویم رومیزی؟ سیستم اطفاء حریق و …) و دوم این که با چی و چطوری پیاده سازی بشه. بعد از این که ایده مشخص بشه، مرحله مرحله پیاده سازیش در همین وبلاگ، گزارش میشه.

Share

پروژه گاه‌شمار

خب، من در گروه های تلگرامی این پیام رو میذاشتم :

دوستی مدتی پیش (که خیلی هم ازش نگذشته ) یک چالش رو بعنوان تمرین برنامه نویسی پیشنهاد داد، و اون هم نوشتن یک API بود برای دریافت ساعت و تاریخ.
من هم وارد این چالش شدم و یک API با روبی و سیناترا نوشتم، روی گیتهاب هم قرارش دادم ولی الان دپلویش کردم که اگر شما هم خواستید بتونید ازش استفاده کنید :
https://gahshomar-api.herokuapp.com/

خب، این هم پروژه ای بود که محسن بعنوان تمرین خواست که ما یه API بنویسیم، من هم این رو با Sinatra نوشتم و الان دپلوی شده و در دسترسه! امیدوارم ازش لذت ببرید 🙂

Share

FreeBSD 11.0-RC1 – نخستین دیدار

امروز بعد از مدتها به وبسایت محبوب و معروف دیستروواچ سر زدم و دیدم که یکی از سیستم عامل های محبوبم یعنی FreeBSD یک نسخه نامزد انتشار منتشر کرده!

خب با خوشحالی تمام دانلودش کردم.

اولین چیزی که در FreeBSD 11 برام جالب شد، این بود که توی نصاب خیلی ریز شده بودن و سوال پرسیده بودن، یعنی عمده پیکربندی رو جزئی از نصاب کردن که این خودش یک پوئن مثبت در نوع خودش محسوب میشه. و یک پیشرفت خیلی بزرگ، چون عمده کاربران FreeBSD مدیران سیستم ها هستند، پس این تیپ پیکربندی هنگام نصب بدرد میخوره.

خب، بعد نصب، تصمیم گرفتم اول pkg رو راه بندازم. بعد nano رو نصب کردم (ادیتور محبوب من در CLI ! یه چیز تنبل پسند و عالی!) ، بعدش تصمیم گرفتم دسکتاپ رو راه اندازی کنم. دیدم توی هندبوک، به gnome3 اشاره شده، اونجا بود که فهمیدم احتمالا گنوم شل دوست داشتنیمون هم اومده به FreeBSD . پس gnome3 رو نصب کردم و این خطوط رو به rc.conf افزودم :

کد   
dbus_enable="YES"
hald_enable="YES"
 
#Running GNOME and GDM services
 
gdm_enable="YES"
gnome_enable="YES"

و بعد از یک ریبوت، چشممون به جمال گنوم شل با 3D Acceleration روشن شد :

و این عکس هم به جهت تایید اصالت سیستم عامل :

در مورد این دسکتاپ، که خب یک دسکتاپ مدرن محسوب میشه و تا مدتها در FreeBSD پیداش نبود، میشه گفت که با اضافه شدنش بدون مشکل به سیستم عامل، میتونه به پیشرفت این سیستم عامل در حوزه دسکتاپ کمک کنه. البته، در کل 11 نرم تر از ۹ و ۱۰ بود که قبل تر تست کرده بودم و حتی به عنوان سیستم عامل اصلی ازشون استفاده میکردم.

موفق باشید 🙂

Share

نوشتن اسمبلی ۳۲ بیت

در گذشته، پست هایی که در مورد اسمبلی قرار دادم، همه در مورد اسمبلی ۱۶ بیت بودن اما حالا میخوایم بریم سراغ اسمبلی ۳۲ بیت. خب فرق ۱۶ با ۳۲ بیت در چیه؟!

اولین نکته، سایز ثبات هاست! در ۱۶ بیت در هر ثبات میتونستیم حداکثر یک مقدار ۴ رقمی هگزادسیمال ذخیره کنیم ولی در ۳۲ بیت این مقدار به ۸ رقم میرسه! حالا خیلی مسائل دیگه مثل دیتاباس و کنترل باس و … که بماند (چون اینجا داریم برنامه نویسی میکنیم و بیشتر با ثبات ها کار داریم).

اینجا، قضیه یه فرقای کوچولویی داره، مثلا اسمبلر nasm قراره استفاده بشه (گرچه قبلا در ساخت اون سیستم عامل کوچک ازش استفاده کردیم) و همچنین وقفه ها و system call هایی که استفاده میکنیم شماره و مقدارشون و مکانشون متفاوته.

بیاید این برنامه رو در نظر بگیریم :

کد   
section .text
	global_start
 
_start:
	mov edx, len
	mov ecx, msg
	mov eax, 0x04
	int 0x80
 
	mov eax, 0x01
	int 0x80
 
section .data
	msg db 'Hello, World!', 0xa
	len equ $ - msg

 

خب در بخش اول، تابعی که نیاز داریم فراخوانی کنیم رو تعریف کردیم. بعدش اومدیم start رو نوشتیم. حالا بیاید این بخش رو بررسی کنیم :

کد   
mov edx, len
mov ecx, msg
mov eax, 0x04
int 0x80

اینجا، مقدار طول رشته ای که خواستیم چاپ کنیم رو توی EDX یا رجیستر داده قرار دادیم. بعدش اومدیم پیامی که میخوایم چاپ بشه رو قرار دادیم درو نECX .

بعدش سیستم کال ۴ یا sys_write رو توی eax قرار دادیم و وقفه ۸۰ رو صدا زدیم. حالا وقفه ۸۰ با مقدار ۴ که توی eax ذخیره شده، میگرده دنبال رشته ای که توی ecx هست و بعدش چاپش میکنه.

حالا بخش دوم کد سگمنت رو بررسی میکنیم :

کد   
mov eax, 0x01
int 0x80

اینجا هم مقدار ۰۱ یا sys_exit رو وارد eax کردیم، تا برنامه پس از اجرا، خارج شه. بعد از این هم باز وقفه ۸۰ رو صدا زدیم.

بخش دیتا هم، مثل همه برنامه های قبلی، تمام داده های مورد نیاز رو با Directive ها تعریف کردیم که بتونیم به راحتی توی کد سگمنت ازشون استفاده کنیم و چون قبلا توضیح داده شده، دیگه دوباره کاری نمی کنم. فقط این پست رو نوشتم تا فرقهای اسمبلی ۳۲ و ۱۶ بیت رو ببینیم. که درآینده بسطش خواهم داد به ۶۴ بیت.

امیدوارم که این پست، بدردتون خورده باشه.

موفق و موید باشید!

Share

درآمدی بر پردازنده ها

ALUwithRegister

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

داکیومنت از اینجا قابل دریافت هست.

با تشکر.

Share

زبان ماشین، رمزگشای دستور العمل

در پست های گذشته بسیار بسیار در مورد زبان ماشین و اسمبلی بحث کردیم، اما این بار میخوایم بررسی کنیم که یک دستور، چطور کار میکنه. برای این کار، ما از ساده ترین دستورات استفاده میکنیم. قبل از اون، باید ببینیم که چه اتفاقی میفته که دستورات ما، شناسایی میشن! پس میایم و دستوراتمون رو بررسی میکنیم.

یک دستور در ماشین چطور خونده میشه؟

این خیلی مهمه که بدونیم یک دستور به چه شکلی خونده میشه. بسیار خوب، دستور زیر رو در نظر بگیرید :

کد   
MOV AX, 0

 

این دستور ماشین کد به این شکل داره :

کد   
B8 0000

 

که البته این ماشین کد، یک ماشین کد هگزادسیمال هست. اون چهار صفری که داریم که مقداری هست که خواستیم توی AX قرار بدیم و باهاش کاری نداریم، ولی B8 ما ، همون دستوریه که لازمه رمزگشایی شه و به صورت دو دویی به این شکل در میاد :

کد   
1011 1000

 

خب ما یک «دیکدر» (که یک مدار متشکل از n ورودی و دو به توان n خروجی هست) داریم، که این اعداد رو به ترتیب روشن و خاموش میکنه، و به این شکله که ما به  دستور میرسیم. در واقع مدارات مربوط به دستور رو خواهیم داشت.

بسیار خوب، حالا که میدونیم چه چیزی باعث میشه که ما بتونیم زبان ماشین رو درک کنیم، بیایم بررسی کنیم که :

زبان ماشین از چند بخش تشکیل شده؟

زبان ماشین، اول به صورت اسمبلی نوشته میشه که به زبون انسان خیلی خیلی نزدیکه. یعنی هرکس کمی انگلیسی بدونه میدونه که کلمه ای مثل ADD یعنی جمع کردن. اما، حالا مشکلی که هست اینه که وقتی «اسمبلی» به «آبجکت کد» یا همون کد هگزادسیمال تبدیل میشه رو هرکسی نمیتونه بخونه. پس راه حل چیه؟

اول باید ببینیم که یک خط آبجکت کد از چیا تشکیل میشه! بیاید این مثال رو در نظر بگیریم باز :

کد   
MOV AX, 0 ;B8 0000

 

خب اینجا من آبجکت کد رو به صورت کامنت در آوردم. دو بخش داریم، یکیش چهارتا صفر، که بهش عملوند یا Operand میگیم و دیگری «کد عملیات» یا Operation Code هست. مثلا برای انتقال به AX همیشه از B8 استفاده میشه. چرا؟ چون اینتل اینطور خواسته 😀 . بعد از این، این کد هگزادسیمال به یک کد باینری تبدیل میشه که CPU میتونه اون رو برای ما اجرا کنه.

از کجا آبجکت کد رو بخونیم؟

همه اسمبلر های موجود میتونن فایلی تولید کنن که آبجکت کد، سمبلهای به کار رفته و … رو شامل شه، و در اسمبلر MASM این فایل با پسوند LST ساخته میشه. شما میتونید با باز کردن این فایل با یک ویرایشگر متنی و خوندنش، ببینید که هر دستوری چه کدی رو داره.

یک برنامه نمونه

خب، من یک برنامه اسمبلی خیلی ساده نوشتم که اجرا کردنش هیچ خروجی ای نداره (:D ) ولی خب آبجکت کد ها تولید شده و اسمبل بدون مشکل صورت گرفته. این برنامه با آبجکت کدهاش به صورت کامنت به این شکله (بررسی دستور MOV در ۱۲ حالت مختلف) :

کد   
.MODEL SMALL
.8086
.STACK 
.DATA
.CODE
MOV AX, 0 ;B8 0000
MOV BX, 0 ;BB 0000
MOV CX, 0 ;B9 0000
MOV DX, 0 ;BA 0000
MOV AH, 0 ;B4 00
MOV BH, 0 ;B7 00
MOV CH, 0 ;B5 00
MOV DH, 0 ;B6 00
MOV AL, 0 ;B0 00
MOV BL, 0 ;B3 00
MOV CL, 0 ;B1 00
MOV DL, 0 ;B2 00
END

برای جلوگیری از ابهام هم مقداری که توی رجیسترها ریخته شده صفر هست، به این شکل کد ماشین بسیار ساده تر شده.

تا پست های بعدی، و اسمبلی بیشتر، موفق و موید و آزاد و شاد باشید! 🙂

Share

گسترش Makefile ها – استفاده از متغیر در Makefile

توی این پست بود که تصمیم گرفتم در مورد نوشتن Makefile توضیح بدم. اما قضیه نوشتن میک فایل، به اون چیزی که اونجا مطرح کردیم محدود نمیشه. میتونیم توی Makefile هامون تعدادی متغیر داشته باشیم. متغیر میتونه کامپایلرمون، ورودی ها و خروجی هاش رو مشخص کنه. حتی سوییچ هایی که برای کامپایل کردن برنامه نیاز داریم میتونیم توی Makefile قرار بدیم. بسیار خوب، خود میک یه دستور echo هم داره که میتونیم برای چاپ پیام ازش استفاده کنیم (به جای استفاده از echo بش). حالا سوال پیش میاد که چطور از این دستور ها و قابلیت ها استفاده میکنیم؟

این خط رو در نظر بگیرید :

کد   
gcc -std=c99 main.c mpc.c -ledit -lm -o main -Wincompatible-pointer-types

الان ما میتونیم هرچی که با L شروع میشه رو توی یک متغیر بریزیم، std رو هم همینطور و همچنین incompatible-pointer-types رو. اینطوری چه سودی بهمون میرسه؟ یک میک فایل تر و تمیز خواهیم داشت. پس به این شکل توی میک فایلمون درش میاریم :

کد   
CC = gcc
STD = -std=c99
LINK = -ledit -lm
FLAGS = -Wincompatible-pointer-types

الان هرچی که لازم بود رو توی متغیرهامون گذاشتیم، ولی نوع استفاده از متغیر هم مهمه. همون کد بالا رو در نظر بگیرید، حالا میایم از متغیرها استفاده میکنیم و به چنین چیزی میرسیم:

کد   
$(CC) $(STD) main.c mpc.c $(LINK) -o main $(FLAGS)

دقت کنید که پرانتز هم برای صدا زدن متغیرها لازمه. الان ما یک میک فایل تر و تمیز داریم. کل میک فایلمون به این شکل در اومده الان :

کد   
CC = gcc
STD = -std=c99
LINK = -ledit -lm
FLAGS = -Wincompatible-pointer-types
all:
	$(CC) $(STD) main.c mpc.c $(LINK) -o main $(FLAGS)
 
clean:
	rm main

خب الان میخوایم یک پیام هم چاپ کنیم و به کاربر خوش آمد بگیم، یا بگیم که صبور باشه و بعد کامپایل شدن پیام کامپایل با موفقیت رو چاپ کنه! کافیه به این فرمت چیزی که میخوایم رو بنویسیم:

کد   
@echo "Compiling proccess may take a long time, please be patient"

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

امیدوارم که این پست هم مفید واقع شده باشه، چون واقعا رفرنس برای نوشتن Makefile توی اینترنت نیست.

موفق و پیروز باشید 🙂

Share

ساخت کراس کامپایلر GCC

اگر لینوکسی باشید (یا حداقل با یکی از سیستم عاملهای خانواده *NIX کار کرده باشید) ، به احتمال خیلی زیاد GCC رو میشناسید. GCC که مخفف GNU Compiler Collection هست یک کامپایلر بزرگ، یا بهتر بگیم یه مجموعه از کامپایلرهاست که توسط پروژه گنو ارائه شده. این کامپایلر به صورت پیشفرض روی تمام توزیع های لینوکس هست (چون چیزیه که عمده ابزارهای لینوکس باهاش کامپایل شدند) و احتمالا روزهای اولی که خواستید توی لینوکس کد C بزنید با این کامپایلر بوده و البته کلی هم فحش دادید بهش 😀 . اگر کمی پیش بریم و برسیم به کسایی که تجربه ساخت LFS رو داشتن، اونها هم احتمالا با کامپایل کردن GCC مواجه شدن. شاید نفس گیر ترین بخش ماجرا در LFS همین GCC باشه ، چون هم طولانیه و هم کلی کانفیگ داره! . اما خب کراس کامپایلر قضیش یکم متفاوته.

من چند وقتیه (خیلی وقته!) درگیر ساخت یک سیستم عاملم و کلی هم برای خودم تحقیق کردم و داکیومنت خوندم و حتی داکیومنت هام رو بازنشر دادم. اما مشکل اینجاست که سیستم عامل قبلیمون کاملا با اسمبلی بود ولی این یکی رو میخوایم با C پیاده سازی کنیم. به نظرتون چی میشه؟ هیچی نمیشه! فقط نیاز داریم تا به جای این که صرفا از NASM استفاده کنیم، جناب GCC که برای خودش غولیه رو هم بازی بدیم. اما اگر سیستممون ۶۴ بیتی باشه چطور؟ اصلا اگر سیستم عامل مقصدمون برای پردازنده ای مثل ARM نوشته شده باشه چی؟ برای این که بتونیم نتیجه و خروجی درست و حسابی بگیریم، نیاز داریم تا کراس کامپایلر داشته باشیم. (برای دونستن اهمیت کراس کامپایلر این لینک رو بخونید).

خب GCC برای کامپایل شدن به Binutils نیاز داره. همچنین قبل از کامپایل Binutils برای معماری مورد نظرمون، باید این کتابخونه ها رو نصب کنیم :

کد   
sudo apt-get install libgmp3-dev libmpfr-dev libmpc-dev texinfo

خب، حالا که این کتابخونه ها رو نصب کردیم میریم که محیط ساخت و ساز (ممکنه درست نباشه ولی باحال ترین معادل ممکن برای Build Environment بود!) رو فراهم کنیم. من میخوام gcc من، برای i686-elf کار کنه. همچنین نمیخوام خیلی پر و بال بدم به ماجرا و نصب رو راحت و با کاربر خودم انجام بدم، پس این کد ها رو وارد ترمینال میکنم تا توی همون پوشه خونگی، gcc مورد نظرمون قرار بگیره!

کد   
export PREFIX="$HOME/opt/cross"
# فراموش نکنید این پوشه رو خودتون باید بسازید 🙂
export TARGET=i686-elf
export PATH="$PREFIX/bin:$PATH"

خب، حالا باید binutils رو از اینجا و gcc رو هم از اینجا دانلود کنید، و سورس ها رو درون پوشه ای به اسم src قرار بدید (پوشه src داخل پوشه خونگی شما قرار داره!). بسیار خوب! توی پوشه src پوشه ای بسازید به اسم build-binutils و سپس سورس binutils رو از حالت فشرده خارج کنید. حالا وارد پوشه build-binutils بشید (هیچی رو وارد این پوشه نکنید!) و سپس تایپ کنید :

کد   
../binutils-*/configure --prefix="$PREFIX" \
--target=$TARGET \
--with-sysroot --disable-nls --disable-werror

بعد از زدن این دستور، اسکریپت configure براتون Makefile درست میکنه. من از نسخه ۲.۲۵ استفاده کردم و واقعا بی مشکل بود، شما هم بهتره از همین نسخه استفاده کنید. حالا که Makefile برامون تولید شده کافیه به ترتیب make و سپس make install رو تایپ کنیم تا binutils مون نصب شه. حالا نوبتی هم باشه نوبت gcc دوست داشتنیه!

خب پوشه build-gcc هم بسازیم و بریم داخلش! حالا باید از فایل configure دوباره برای ساختن Makefile استفاده کنیم!

کد   
../gcc-*/configure --prefix="$PREFIX" \
--target="$TARGET" \
--disable-nls \
--enable-languages=c,c++ \
--without-headers

بعد از انجام این مرحله، باید یکی یکی دستورات زیر رو بزنیم :

کد   
make all-gcc
make all-target-libgcc
make install-gcc
make install-target-libgcc

تا gcc برامون نصب شه! الان با فراخوانی دستوری مثل i686-elf-gcc ، میتونیم به gcc ساخته شدمون دسترسی پیدا کنیم!

امیدوارم که این مطلب مفید واقع شده باشه، موفق باشید 🙂

Share

بازی با سوییفت

زبان برنامه نویسی سوییفت ، زبانی که اپل ارائه کرده و همچنین به تازگی هم اوپن سورس شده. این زبان یه زبان باحال، قشنگ و خوش ساخته، و البته قشنگی ماجرا اینه که خیلی راحت میشه روی لینوکس یا FreeBSD و … هم اجراش کرد. فرمورک Foundation هم که یکی از فرمورکهای کلیدی اپل بوده، برای این زبان به صورت اوپن سورس ارائه شده، و این یعنی اوپن سورس بیش از پیش بهشت برنامه نویسان شده (با این حساب حتی اگر دیوایس اپل ندارید میتونید این زبان رو یاد بگیرید و تمرین کنید). بسیار خوب، بریم سراغ این که ببینیم این زبان چه شکلیه و چطوریه! اول از همه این که سینتکس کاملا شبیه Objective C داره، و اگر قبلا آبجکتیو سی کد زدید، سوییفت یاد گرفتن براتون بی نهایت آسون میشه. خب، اولین مثال و به نوعی مثال روتین برای آشنا شدن با یک زبان، یا همون «سلام دنیا» (که در مقاله پیشین بهش اشاره شد) ، به این شکله :

کد   
print("Hello, World!")

خب، این روش برای چاپ رشته خیلی مرسومه (استفاده از یه تابع چاپ و یک رشته) ، اما برای این که مفاهیم بهتر منتقل شن، میتونیم رشته رو داخل یک متغیر بریزیم :

کد   
var welcomeMessage: String = "Hello, World"

خب الان که متغیر welcomeMessage رو داریم میریم که چاپش کنیم :

کد   
print(welcomeMessage)

خب میخوایم بریم سراغ چیزایی که توی یه زبان خیلی مرسومن، مثلا حلقه while و این چیزا! خب اگر C و Objective C و این زبانا رو بلد باشید خیلی کارتون راحته چون دقیقا همونه :

کد   
while(true){
 print(welcomeMessage)
 }

خب این هم چاپ بی نهایت همون پیامی که توی متغیر welcomeMessage ریختیم 😀 . برای اطلاعات بیشتر از ساختارهای کنترلی میتونید این لینک رو بخونید.

بسیار خوب، ساختار فانکشن ها هم همونطور شبیه C و Objective C و البته شبیه Go هم هست! این یه تابع بازگشتیه (که البته توی REPL زبان خیلی اذیتم کرد ولی موقع کامپایل خیلی مظلومانه (:D) اجرا شد!

کد   
func factorial(x: UInt) -> UInt {
 if(x == 0) {
   return 1
   } else {
   return x * factorial(x - 1)
   }
 }

خب این تابع یک عدد صحیح بدون علامت رو میگیره و فاکتوریلش رو حساب میکنه و بعد بر میگردونه، همونطور که دیدید اگر با زبان های شبیه C آشنا باشید خواهید دید که تقریبا هیچ فرق خاصی از نظر سینتکس نداره. فقط باید یک مقدار روی دیتاتایپ ها و … دقیق بشید تا بفهمید قضیه چیه وگرنه در کل اصلا زبان سختی نیست. اگر میخواید یادش بگیرید کتابی که خود اپل ارائه کرده رو میتونید دریافت کنید (روی iBooks هم هست!).

امیدوارم که این مطلب مفید واقع شده باشه.

موفق باشید 🙂

Share

نوشتن Makefile برای تسریع فرایند ساخت

احتمال خیلی زیاد، همه ما یک بار توی عمرمون این صحنه رو دیدیم :

کد   
make
make install
make clean

خب ما وقتی یه سورس کدی رو دریافت میکنیم معمولا همراهشم یه Makefile داریم، سازنده اون برنامه، یا همون دوست عزیزی که سورس کد رو برامون نوشته، میتونست بگه کسی که دانلود کرد دیگه خودش بشینه یکی یکی کد ها رو کامپایل کنه و آخرش لینک کنه و این حرفا. ولی خب چون همه توانایی، وقت یا دانش لازم رو ندارن، معمولا یه Makefile نوشته میشه که این کارها درونش صورت بگیره! توی این پست، قراره ما یاد بگیریم که چطور Makefile بنویسیم. اول ببینیم make چیه؟ همونطور که میدونید make به معنای ساختنه. و نرم افزار make هم ساخته شده که بسازه. طبق تعریفی که توی ویکیپدیا و صفحه رسمیش هست، میگن که «نرم افزاریه که فایل های قابل اجرا از یک سری سورس تولید میکنه». البته کارهای دیگری هم میشه باهاش کرد! مثلا همون سورس ها و … رو باهاش منتقل کنیم به جایی که میخوایم و از این قبیل کارا. خب برای نوشتن یک Makefile نیاز به یک ادیتور متنی، نرم افزار make (دقت کنید این نرم افزار جزئی از استاندارد POSIX به حساب میاد و معمولا روی همه یونیکس-لایک ها نصبه)، یک محیط یونیکس لایک (اگر ویندوزی هستید Cygwin یا یک یونیکس لایک مجازی) نیاز داریم. همین؟ درسته همین. حالا با make قراره چی کار کنیم؟ اول بیایم یه Makefile ساده بنویسیم.

سناریوی کلی ما استفاده از نرم افزار echo هست که اونم در یونیکس لایک ها موجوده. ما میخوایم با استفاده از make و echo پیام معروف Hello, World رو نشون بدیم :

کد   
all:
	echo "Hello, World"

خب اینجا دو تا توضیح داریم :

یکی این که all چیه؟ این all یه سوییچ عمومی هست که توی همه Makefile ها موجوده. وقتی که شما صرفا تایپ کنید make هرچی که به این سوییچ گفته شده اجرا میشه، حالا میتونه روی فایل خاصی تغییر اعمال کنه یا نه، مثل ما صرفا یکی از برنامه ها رو فراخوانی کنه. و این که اون فاصله زیاد برای چیه؟ هر وقت نوشتید all (یا هر سوییچ دیگه ای) ، کافیه بیاید خط بعدی و Tab رو بزنید (دقت کنید مطلقا از Space استفاده نکنید چون با هم فرق دارن!) و دستور مورد نظرتون رو وارد کنید!. الان میتونید این تکه کد رو در یک فایل به اسم Makefile ذخیره کنید و بعدش تایپ کنید make و نتیجه رو ببینید! خواهید دید اول دستوری که بهش دادیم و سپس نتیجش رو نشون میده.

بسیار خوب! بیایم یک سناریوی دیگه پیاده کنیم. فرض کنیم شما اومدید :

یک برنامه به زبان C نوشتید، و الان میخواید اون رو کامپایل کنید، در یک دایرکتوری خاص به اسم path (که زیرشاخه دایرکتوری Root هست) قرار بدید، و سپس با یک دستور فایل باینری رو از دایرکتوری سورس حذف کنید. 

قطعا به صورت دستی هم میشه انجام داد، ولی خب منطقی ترش اینه که بیایم و از Makefile استفاده کنیم! فرض میکنیم اسم سورس شما src.c هست و در دایرکتوری ای قرار داره! خب میک فایل ما به این شکل میشه :

کد   
all: src.c
	gcc -o src src.c
 
install: src
	cp -v src /path
 
clean: src
	rm -v src

خب برای این که اینجا، ما سوییچ های all و install و clean رو روی فایلهای مورد نظرمون اعمال کنیم، اسم فایل های مورد نظر رو جلوی سوییچ ها قرار دادیم. توی all میاد از src.c یک فایل باینری به اسم src میسازه! توی install هم اون باینری رو کپی میکنه توی path (البته چون path زیرشاخه دایرکتوری ریشه ماست، باید make رو با sudo اجرا کنید و فکر کنم ترکیب sudo و make و install شدیدا براتون آشناس 😀 )، توی clean هم اومدیم اون فایل باینری رو پاک کردیم! به همین سادگی!

توی این پست سعی کردم تا حد امکان، ساده توضیح بدم چرا که واقعا ساده تر از این نمیشد make رو توضیح داد. البته میشه Makefile های بسیار پیچیده تری هم نوشت که همه می بینیم هستن! مثلا Makefile های FreeBSD هر کدوم غولی به حساب میان. ولی برای پروژه های ساده، خوندن و دونستن همین پست هم کافیه.

امیدوارم که این پست به دردتون خورده باشه، موفق باشید 🙂

Share