Buildroot - حصہ 1. عمومی معلومات، ایک کم سے کم نظام کو جمع کرنا، مینو کے ذریعے ترتیب

تعارف

مضامین کی اس سیریز میں، میں بلڈروٹ ڈسٹری بیوشن بلڈ سسٹم کو دیکھنا چاہتا ہوں اور اسے اپنی مرضی کے مطابق بنانے میں اپنا تجربہ بتانا چاہتا ہوں۔ گرافیکل انٹرفیس اور کم سے کم فعالیت کے ساتھ ایک چھوٹا OS بنانے کا عملی تجربہ ہوگا۔

سب سے پہلے، آپ کو تعمیراتی نظام اور تقسیم کو الجھانا نہیں چاہیے۔ Buildroot پیکجوں کے ایک سیٹ سے ایک سسٹم بنا سکتا ہے جو اسے پیش کیے جاتے ہیں۔ بلڈروٹ میک فائلز پر بنایا گیا ہے اور اس وجہ سے اس میں حسب ضرورت کی زبردست صلاحیتیں ہیں۔ ایک پیکج کو دوسرے ورژن سے بدلیں، اپنا پیکج شامل کریں، پیکج بنانے کے لیے اصول تبدیل کریں، تمام پیکجز انسٹال کرنے کے بعد فائل سسٹم کو اپنی مرضی کے مطابق بنائیں؟ buildroot یہ سب کر سکتا ہے۔

روس میں، buildroot استعمال کیا جاتا ہے، لیکن میری رائے میں ابتدائیوں کے لیے روسی زبان میں بہت کم معلومات ہیں۔

کام کا مقصد لائیو ڈاؤن لوڈ، icewm انٹرفیس اور براؤزر کے ساتھ ڈسٹری بیوشن کٹ کو جمع کرنا ہے۔ ہدف پلیٹ فارم ورچوئل باکس ہے۔

اپنی تقسیم کیوں بنائیں؟ اکثر محدود وسائل کے ساتھ محدود فعالیت کی ضرورت ہوتی ہے۔ اس سے بھی زیادہ کثرت سے آٹومیشن میں آپ کو فرم ویئر بنانے کی ضرورت ہوتی ہے۔ غیر ضروری پیکجوں کو صاف کرکے اور اسے فرم ویئر میں تبدیل کرکے عام مقصد کی تقسیم کو ڈھالنا نئی تقسیم کی تعمیر سے زیادہ محنت طلب ہے۔ جینٹو کے استعمال کی بھی اپنی حدود ہیں۔

Buildroot سسٹم بہت طاقتور ہے، لیکن یہ آپ کے لیے کچھ نہیں کرے گا۔ یہ صرف اسمبلی کے عمل کو فعال اور خودکار کر سکتا ہے۔

متبادل تعمیراتی نظام (یوکٹو، اوپن بلڈ سسٹم اور دیگر) پر غور یا موازنہ نہیں کیا جاتا ہے۔

کہاں سے حاصل کریں اور کیسے شروع کریں۔

پروجیکٹ کی ویب سائٹ - buildroot.org. یہاں آپ موجودہ ورژن ڈاؤن لوڈ کر سکتے ہیں اور دستی پڑھ سکتے ہیں۔ وہاں آپ کمیونٹی سے رابطہ کر سکتے ہیں، وہاں ایک بگ ٹریکر، میل لسٹ اور ایک آئی آر سی چینل ہے۔

بلڈروٹ بلڈ کے ٹارگٹ بورڈ کے لیے ڈیف کنفیگس چلاتا ہے۔ Defconfig ایک کنفیگریشن فائل ہے جو صرف ان اختیارات کو اسٹور کرتی ہے جن کی ڈیفالٹ ویلیوز نہیں ہوتی ہیں۔ یہ وہی ہے جو طے کرتا ہے کہ کیا جمع کیا جائے گا اور کیسے۔ اس صورت میں، آپ busybox، linux-kernel، uglibc، u-boot اور barebox bootloaders کے کنفیگرز کو الگ سے ترتیب دے سکتے ہیں، لیکن ان سب کو ٹارگٹ بورڈ سے جوڑ دیا جائے گا۔
ڈاؤن لوڈ کردہ آرکائیو کو پیک کرنے یا گٹ سے کلوننگ کرنے کے بعد، ہمیں استعمال کے لیے تیار بلڈروٹ ملتا ہے۔ آپ دستی میں ڈائریکٹری کے ڈھانچے کے بارے میں مزید پڑھ سکتے ہیں؛ میں آپ کو سب سے اہم کے بارے میں بتاؤں گا:

بورڈ - ہر بورڈ کے لیے مخصوص فائلوں کے ساتھ ایک ڈائریکٹری۔ یہ سسٹم امیجز (iso، sdcart، cpio اور دیگر) بنانے کے لیے اسکرپٹ ہو سکتے ہیں، ایک اوورلے ڈائرکٹری، kernel config، وغیرہ۔
تشکیل - بورڈ کی اصل ڈیف کنفیگ۔ Defconfig ایک نامکمل بورڈ کنفیگریشن ہے۔ یہ صرف پیرامیٹرز کو اسٹور کرتا ہے جو پہلے سے طے شدہ ترتیبات سے مختلف ہوتے ہیں۔
dl - اسمبلی کے لیے ڈاؤن لوڈ کردہ سورس کوڈز/فائلوں کے ساتھ ڈائریکٹری
آؤٹ پٹ/ٹارگٹ - نتیجے میں OS کا جمع فائل سسٹم۔ اس کے بعد، ڈاؤن لوڈ/انسٹالیشن کے لیے اس سے تصاویر بنائی جاتی ہیں۔
آؤٹ پٹ/میزبان - اسمبلی کے لیے میزبان یوٹیلیٹیز
آؤٹ پٹ/تعمیر - جمع شدہ پیکیجز

اسمبلی کو KConfig کے ذریعے ترتیب دیا گیا ہے۔ اسی نظام کو لینکس کرنل بنانے کے لیے استعمال کیا جاتا ہے۔ سب سے زیادہ استعمال ہونے والے کمانڈز کی فہرست (بلڈروٹ ڈائرکٹری میں عمل کریں):

  • make menuconfig - بلڈ کنفیگریشن کو کال کریں۔ آپ گرافیکل انٹرفیس بھی استعمال کر سکتے ہیں (make nconfig، make xconfig، make gconfig)
  • linux-menuconfig بنائیں - کرنل کنفیگریشن کو کال کریں۔
  • صاف کریں - تعمیراتی نتائج کو صاف کریں (آؤٹ پٹ میں ذخیرہ شدہ ہر چیز)
  • بنائیں - ایک نظام بنائیں۔ یہ پہلے سے جمع شدہ عمل کو دوبارہ نہیں جوڑتا ہے۔
  • defconfig_name بنائیں - ترتیب کو ایک مخصوص defconfig میں تبدیل کریں۔
  • list-defconfigs بنائیں - defconfigs کی فہرست دکھائیں۔
  • ماخذ بنائیں - بغیر عمارت کے صرف انسٹالیشن فائلوں کو ڈاؤن لوڈ کریں۔
  • مدد کریں - ممکنہ کمانڈز کی فہرست بنائیں

اہم نوٹ اور مفید مشورے۔

Buildroot ان پیکجوں کو دوبارہ نہیں بناتا جو پہلے ہی بن چکے ہیں! لہٰذا، ایسی صورت حال پیدا ہو سکتی ہے جہاں ایک مکمل دوبارہ اسمبلی کی ضرورت ہو۔

آپ کمانڈ کے ساتھ ایک علیحدہ پیکیج دوبارہ بنا سکتے ہیں۔ پیکیج کا نام دوبارہ بنائیں۔ مثال کے طور پر، آپ لینکس کرنل کو دوبارہ بنا سکتے ہیں:

make linux-rebuild

Buildroot آؤٹ پٹ/build/$packagename ڈائرکٹری میں سٹیمپ فائلیں بنا کر کسی بھی پیکیج کی حالت کو اسٹور کرتا ہے۔

Buildroot - حصہ 1. عمومی معلومات، ایک کم سے کم نظام کو جمع کرنا، مینو کے ذریعے ترتیب

لہذا، آپ روٹ-fs اور امیجز کو بغیر پیکجوں کی تعمیر کے دوبارہ بنا سکتے ہیں۔

rm output/build/host-gcc-final-*/.stamp_host_installed;rm -rf output/target;find output/ -name ".stamp_target_installed" |xargs rm -rf ; make

مفید متغیرات

buildroot میں آسان ترتیب کے لیے متغیرات کا ایک سیٹ ہے۔

  • $TOPDIR - buildroot ڈائریکٹری
  • $BASEDIR - آؤٹ پٹ ڈائرکٹری
  • $HOST_DIR، $STAGING_DIR، $TARGET_DIR — میزبان fs، staging fs، ٹارگٹ fs بلڈ ڈائرکٹریز۔
  • $BUILD_DIR - غیر پیک شدہ اور تعمیر شدہ پیکجوں کے ساتھ ڈائریکٹری

تصور

buildroot میں ویژولائزیشن کی خصوصیت ہے۔ آپ حتمی نظام میں انحصاری خاکہ، ایک بلڈ ٹائم گراف، اور پیکیج سائز کا گراف بنا سکتے ہیں۔ نتائج آؤٹ پٹ/گراف ڈائرکٹری میں پی ڈی ایف فائلوں کی شکل میں ہیں (آپ ایس وی این، پی این جی سے انتخاب کر سکتے ہیں)۔

تصور کے احکامات کی مثالیں:

  • make graph-depends انحصار درخت بنائیں
  • make <pkg>-graph-depends ایک مخصوص پیکج کے لیے انحصار کا درخت بنائیں
  • BR2_GRAPH_OUT=png make graph-build PNG آؤٹ پٹ کے ساتھ پلاٹ کی تعمیر کا وقت
  • make graph-size پلاٹ پیکٹ کا سائز

مفید اسکرپٹس

بلڈروٹ ڈائرکٹری میں ایک ذیلی ڈائرکٹری ہے۔ utils مفید اسکرپٹ کے ساتھ۔ مثال کے طور پر، ایک اسکرپٹ ہے جو پیکیج کی تفصیل کی درستگی کو چیک کرتا ہے۔ یہ آپ کے اپنے پیکجوں کو شامل کرتے وقت مفید ہو سکتا ہے (میں یہ بعد میں کروں گا)۔ فائل utils/readme.txt ان اسکرپٹس کی تفصیل پر مشتمل ہے۔

آئیے اسٹاک کی تقسیم بنائیں

یہ یاد رکھنا ضروری ہے کہ تمام کارروائیاں ایک باقاعدہ صارف کی طرف سے کی جاتی ہیں، جڑ کی نہیں۔
تمام کمانڈز کو بلڈروٹ میں نافذ کیا جاتا ہے۔ buildroot پیکیج میں پہلے سے ہی بہت سے عام بورڈز اور ورچوئلائزیشن کے لیے ترتیب کا ایک سیٹ شامل ہے۔

آئیے کنفیگریشنز کی فہرست دیکھتے ہیں:

Buildroot - حصہ 1. عمومی معلومات، ایک کم سے کم نظام کو جمع کرنا، مینو کے ذریعے ترتیب

qemu_x86_64_defconfig ترتیب پر جائیں۔

make qemu_x86_64_defconfig

اور ہم اسمبلی شروع کرتے ہیں۔

make

تعمیر کامیابی سے مکمل ہوئی، نتائج دیکھیں:

Buildroot - حصہ 1. عمومی معلومات، ایک کم سے کم نظام کو جمع کرنا، مینو کے ذریعے ترتیب

Buildroot نے ایسی تصاویر مرتب کی ہیں جنہیں آپ Qemu میں چلا سکتے ہیں اور تصدیق کر سکتے ہیں کہ وہ کام کرتی ہیں۔

qemu-system-x86_64 -kernel output/images/bzImage -hda    output/images/rootfs.ext2 -append "root=/dev/sda rw" -s -S

نتیجہ qemu میں چلنے والا ایک نظام ہے:

Buildroot - حصہ 1. عمومی معلومات، ایک کم سے کم نظام کو جمع کرنا، مینو کے ذریعے ترتیب

اپنی خود کی بورڈ کی ترتیب بنانا

بورڈ فائلوں کو شامل کرنا

آئیے کنفیگریشنز کی فہرست دیکھتے ہیں:

Buildroot - حصہ 1. عمومی معلومات، ایک کم سے کم نظام کو جمع کرنا، مینو کے ذریعے ترتیب

فہرست میں ہم pc_x86_64_efi_defconfig دیکھتے ہیں۔ ہم اسے ترتیب سے کاپی کرکے اپنا بورڈ بنائیں گے:

cp configs/pc_x86_64_bios_defconfig configs/my_x86_board_defconfig

آئیے فوری طور پر اپنے اسکرپٹس، روٹ ایف ایس اوورلے اور دیگر ضروری فائلوں کو ذخیرہ کرنے کے لیے بورڈ ڈائرکٹری بنائیں:

mkdir board/my_x86_board

اس defconfig پر سوئچ کریں:

make my_x86_board_defconfig

اس طرح، اب بلڈ کنفگ (جو بلڈ روٹ ڈائرکٹری کے روٹ میں .config میں محفوظ ہے) x86-64 لیگیسی (bios) بوٹ ٹارگٹ مشین سے مطابقت رکھتا ہے۔

آئیے لینکس کرنل کنفیگریشن کو کاپی کرتے ہیں (بعد میں مفید):

cp board/pc/linux.config board/my_x86_board/

KConfig کے ذریعے تعمیراتی پیرامیٹرز ترتیب دینا

آئیے سیٹ اپ شروع کریں:

make menuconfig 

KConfig ونڈو کھل جائے گی۔ گرافیکل انٹرفیس کے ساتھ ترتیب دینا ممکن ہے (nconfig بنائیں، xconfig بنائیں، gconfig بنائیں):

Buildroot - حصہ 1. عمومی معلومات، ایک کم سے کم نظام کو جمع کرنا، مینو کے ذریعے ترتیب

ہم پہلا سیکشن ٹارگٹ آپشنز داخل کرتے ہیں۔ یہاں آپ ٹارگٹ فن تعمیر کو منتخب کر سکتے ہیں جس کے لیے تعمیر کی جائے گی۔

Buildroot - حصہ 1. عمومی معلومات، ایک کم سے کم نظام کو جمع کرنا، مینو کے ذریعے ترتیب

تعمیر کے اختیارات - یہاں تعمیر کی مختلف ترتیبات ہیں۔ آپ سورس کوڈز، بلڈ تھریڈز کی تعداد، سورس کوڈز ڈاؤن لوڈ کرنے کے لیے آئینے اور دیگر سیٹنگز کے ساتھ ڈائریکٹریز کی وضاحت کر سکتے ہیں۔ آئیے سیٹنگز کو ڈیفالٹ پر چھوڑ دیں۔

ٹول چین - تعمیراتی ٹولز خود یہاں ترتیب دیے گئے ہیں۔ اس کے بارے میں مزید پڑھیں۔

Buildroot - حصہ 1. عمومی معلومات، ایک کم سے کم نظام کو جمع کرنا، مینو کے ذریعے ترتیب

ٹول چین کی قسم - استعمال شدہ ٹول چین کی قسم۔ یہ ایک ٹول چین ہو سکتا ہے جو بلڈروٹ میں بنایا گیا ہو یا ایک بیرونی (آپ ڈائرکٹری کو پہلے سے بنی ہوئی ایک یا ڈاؤن لوڈ کرنے کے لیے یو آر ایل کے ساتھ بتا سکتے ہیں)۔ مختلف فن تعمیرات کے لیے اضافی اختیارات ہیں۔ مثال کے طور پر، بازو کے لیے آپ صرف بیرونی ٹول چین کے لینارو ورژن کو منتخب کر سکتے ہیں۔

سی لائبریری - سی لائبریری کا انتخاب۔ پورے نظام کا عمل اسی پر منحصر ہے۔ عام طور پر، glibc استعمال کیا جاتا ہے، جو تمام ممکنہ فعالیت کو سپورٹ کرتا ہے۔ لیکن ایمبیڈڈ سسٹم کے لیے یہ بہت بڑا ہو سکتا ہے، اس لیے uglibc یا musl کو اکثر منتخب کیا جاتا ہے۔ ہم glibc کو منتخب کریں گے (اس کی ضرورت بعد میں systemd استعمال کرنے کے لیے ہوگی)۔

کرنل ہیڈرز اور کسٹم کرنل ہیڈرز سیریز - دانا کے اس ورژن سے مماثل ہونا چاہیے جو اسمبل شدہ سسٹم میں ہوگا۔ کرنل ہیڈرز کے لیے، آپ ٹربال یا گٹ ریپوزٹری کا راستہ بھی بتا سکتے ہیں۔

جی سی سی کمپائلر ورژنز - کمپائلر ورژن کو منتخب کریں جسے تعمیر کرنے کے لیے استعمال کیا جائے۔
C++ سپورٹ کو فعال کریں - سسٹم میں C++ لائبریریوں کے لیے سپورٹ کے ساتھ تعمیر کرنے کا انتخاب کریں۔ یہ مستقبل میں ہمارے لیے مفید ہو گا۔

اضافی جی سی سی اختیارات - آپ اضافی کمپائلر کے اختیارات ترتیب دے سکتے ہیں۔ ہمیں ابھی اس کی ضرورت نہیں ہے۔

سسٹم کنفیگریشن آپ کو بنائے گئے سسٹم کے مستقبل کے پیرامیٹرز سیٹ کرنے کی اجازت دیتی ہے:

Buildroot - حصہ 1. عمومی معلومات، ایک کم سے کم نظام کو جمع کرنا، مینو کے ذریعے ترتیب

عنوان سے زیادہ تر نکات واضح ہیں۔ آئیے درج ذیل نکات پر توجہ دیں:
صارفین کی میزوں کا راستہ - صارفین کے ساتھ ٹیبل بنایا جانا ہے (https://buildroot.org/downloads/manual/manual.html#makeuser-syntax).

مثال کی فائل۔ صارف صارف کو پاس ورڈ ایڈمن کے ساتھ بنایا جائے گا، خود بخود gid/uid، /bin/sh شیل، ڈیفالٹ گروپ یوزر، گروپ ممبر روٹ، کمنٹ فو یوزر

[alexey@alexey-pc buildroot ]$ cat board/my_x86_board/users.txt 
user -1 user -1 =admin /home/user /bin/sh root Foo user

روٹ فائل سسٹم اوورلے ڈائرکٹریز - ڈائرکٹری جو اسمبل شدہ ٹارگٹ-fs کے اوپر لی گئی ہے۔ نئی فائلوں کو شامل کرتا ہے اور موجودہ فائلوں کو تبدیل کرتا ہے۔

فائل سسٹم امیجز بنانے سے پہلے چلانے کے لیے حسب ضرورت اسکرپٹس - فائل سسٹم کو امیجز میں فولڈ کرنے سے پہلے فوری طور پر اسکرپٹس کو عمل میں لایا جاتا ہے۔ آئیے اسکرپٹ کو ابھی کے لیے خالی چھوڑ دیں۔

آئیے کرنل سیکشن پر چلتے ہیں۔

Buildroot - حصہ 1. عمومی معلومات، ایک کم سے کم نظام کو جمع کرنا، مینو کے ذریعے ترتیب

کرنل سیٹنگز یہاں سیٹ ہیں۔ دانا خود make linux-menuconfig کے ذریعے ترتیب دیا گیا ہے۔
آپ کرنل ورژن کو مختلف طریقوں سے ترتیب دے سکتے ہیں: پیش کردہ ان میں سے منتخب کریں، ورژن کو دستی طور پر درج کریں، ذخیرہ خانہ یا ریڈی میڈ ٹربال کی وضاحت کریں۔

کرنل کنفیگریشن - کرنل کنفیگریشن کا راستہ۔ آپ لینکس سے منتخب فن تعمیر یا defocnfig کے لیے ڈیفالٹ کنفیگریشن منتخب کر سکتے ہیں۔ لینکس سورس میں مختلف ٹارگٹ سسٹمز کے لیے ڈیف کنفیگس کا ایک سیٹ ہوتا ہے۔ آپ اپنی ضرورت کو تلاش کر سکتے ہیں۔ یہاں کے ذرائع کو براہ راست دیکھ کر. مثال کے طور پر، ایک بیگل بون بلیک بورڈ کے لیے آپ کر سکتے ہیں۔ تشکیل منتخب کریں۔.

ٹارگٹ پیکجز سیکشن آپ کو یہ منتخب کرنے کی اجازت دیتا ہے کہ کون سے پیکجز بنائے جا رہے سسٹم پر انسٹال ہوں گے۔ آئیے اسے ابھی کے لیے غیر تبدیل شدہ چھوڑ دیں۔ ہم بعد میں اپنے پیکجوں کو اس فہرست میں شامل کریں گے۔
فائل سسٹم امیجز - فائل سسٹم کی تصاویر کی فہرست جو جمع کی جائیں گی۔ ایک آئی ایس او امیج شامل کریں۔

Buildroot - حصہ 1. عمومی معلومات، ایک کم سے کم نظام کو جمع کرنا، مینو کے ذریعے ترتیب

بوٹ لوڈرز - جمع کرنے کے لیے بوٹ لوڈرز کا انتخاب۔ آئیے isolinix کا انتخاب کریں۔

Buildroot - حصہ 1. عمومی معلومات، ایک کم سے کم نظام کو جمع کرنا، مینو کے ذریعے ترتیب

سسٹم ڈی کو ترتیب دینا

Systemd کرنل اور glibc کے ساتھ لینکس کے ستونوں میں سے ایک بن رہا ہے۔ لہذا، میں نے اس کی ترتیب کو ایک علیحدہ آئٹم میں منتقل کر دیا ہے۔

make menuconfig کے ذریعے ترتیب دیا گیا، پھر ٹارگٹ پیکجز → سسٹم ٹولز → systemd۔ یہاں آپ بتا سکتے ہیں کہ کون سی سسٹمڈ سروسز انسٹال ہوں گی اور سسٹم شروع ہونے پر شروع کی جائیں گی۔

Buildroot - حصہ 1. عمومی معلومات، ایک کم سے کم نظام کو جمع کرنا، مینو کے ذریعے ترتیب

سسٹم کی ترتیب کو محفوظ کرنا

ہم اس ترتیب کو KConfig کے ذریعے محفوظ کرتے ہیں۔

پھر ہمارے defconfig کو محفوظ کریں:

make savedefconfig

لینکس کرنل کنفیگریشن

لینکس کرنل کنفیگریشن کو درج ذیل کمانڈ کے ساتھ پکارا جاتا ہے۔

make linux-menuconfig

آئیے ورچوئل باکس ویڈیو کارڈ کے لیے سپورٹ شامل کریں۔

Buildroot - حصہ 1. عمومی معلومات، ایک کم سے کم نظام کو جمع کرنا، مینو کے ذریعے ترتیب

آئیے ورچوئل باکس گیسٹ انٹیگریشن سپورٹ شامل کریں۔

Buildroot - حصہ 1. عمومی معلومات، ایک کم سے کم نظام کو جمع کرنا، مینو کے ذریعے ترتیب

محفوظ کریں اور باہر نکلیں۔ IMPORTANT: کنفیگریشن کو output/build/linux-$version/config میں محفوظ کیا جائے گا، لیکن board/my_x86_board/linux.config میں نہیں

Buildroot - حصہ 1. عمومی معلومات، ایک کم سے کم نظام کو جمع کرنا، مینو کے ذریعے ترتیب

لہذا، آپ کو دستی طور پر ترتیب کو اسٹوریج کے مقام پر کاپی کرنے کی ضرورت ہے:

cp output/build/linux-4.19.25/.config board/my_x86_board/linux.config

جس کے بعد ہم پورے نظام کی مکمل دوبارہ اسمبلی کریں گے۔ buildroot جو پہلے سے بنایا گیا ہے اسے دوبارہ نہیں بناتا، آپ کو دوبارہ تعمیر کرنے کے لیے پیکجوں کو دستی طور پر بتانا ہوگا۔ وقت اور اعصاب کو ضائع نہ کرنے کے لیے، ایک چھوٹے سے نظام کو مکمل طور پر دوبارہ بنانا آسان ہے):

make clean;make

اسمبلی کی تکمیل پر، ورچوئل باکس (ورژن 5.2 اور 6.0 پر تجربہ کیا گیا) سی ڈی سے بوٹنگ شروع کریں۔ سسٹم کے پیرامیٹرز:

Buildroot - حصہ 1. عمومی معلومات، ایک کم سے کم نظام کو جمع کرنا، مینو کے ذریعے ترتیب

جمع شدہ آئی ایس او سے لانچ کریں:

Buildroot - حصہ 1. عمومی معلومات، ایک کم سے کم نظام کو جمع کرنا، مینو کے ذریعے ترتیب

استعمال شدہ مواد کی فہرست

  1. بلڈروٹ دستی

ماخذ: www.habr.com

نیا تبصرہ شامل کریں