امبدد لینوکس – قسمت سیزدهم – کار با crosstool-NG – زنجیره‌ای از ابزارهای لازم برای ساختن همه چیز (بخش نهم)

0
242

(فصل دوم – بخش نهم)

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

 

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

همه آموزش‌های امبدد لینوکس

استاتیک یا داینامیک

هر برنامه‌ای که واسه لینوکس به زبان C/C++ می‌نویسم به یه سری کتابخانه‌ها نیاز داره که حداقلش همون libc هست که به صورت پیش فرض با همه برنامه‌ها لینک هست و نیازی نیست به کامپایلر بگیم لینکش کن.
بقیه کتابخانه‌ها رو با آپشن –l به کامپایلر میگیم لینک کنه.
این لینک کردن به دو صورت استاتیک و داینامیک میتونه انجام بشه.
استاتیک یعنی تمام توابعی که برنامه ما استفاده میکنه و وابسته‌هاشون همشون از کتابخانه اصلی استخراج می‌شن و توی برنامه اجرایی ما گونجونده میشه.
داینامیک یعنی ارجاعات به فایل‌های کتابخانه و توابعش در کد هست ولی لینک اصلی هنگام اجرا صورت میگیره.
کاربرد استایتک بیشتر زمانی هست که ما میخوایم در مصرف حافظه صرفه جویی کنیم یا مجبوریم صرفه جویی کنیم و برنامه‌های زیادی هم نداریم. مثلا میخوایم کل سیستم عامل و برنامه‌هاش رو روی یه SPI فش جا بدیم.
توی امبددهای امروزی بیشتر از حالت داینامیک استفاده میشه و در این حالت دونستن ورژن‌های کتابخانه‌ها مهمه.

چرا اینقدر کتابخانه با یک اسم داریم

مثلا یه نگاهی به این خروجی بندازین

ls usr/lib/libmenu*
usr/lib/libmenu.a usr/lib/libmenu.so.5
usr/lib/libmenu.so usr/lib/libmenu.so.5.9

 

خوب یکم دقیقتر بش نگاه کنیم:

ls -l usr/lib/libmenu*
-r--r--r-- 1 at00 at00 60710 Aug 30 2020 usr/lib/libmenu.a
lrwxrwxrwx 1 at00 at00 12 Aug 30 2020 usr/lib/libmenu.so -> libmenu.so.5
lrwxrwxrwx 1 at00 at00 14 Aug 30 2020 usr/lib/libmenu.so.5 -> libmenu.so.5.9
-r-xr-xr-x 1 at00 at00 48316 Aug 30 2020 usr/lib/libmenu.so.5.9

کتابخانه libmenu.a واسه زمانی هست که میخوایم استایتک بیلد کنیم.
libmenu.so.5.9 که کتابخانه اصلی هست واسه داینامیک لینک ولی چرا این دو تا سافت لینک (شرتکات!) رو داریم libmenu.so libmenu.so.5؟
libmenu.so واسه داینامیک لینک زمان کامپایل هست و libmenu.so.5 هم یک soname هست و در زمان اجرا ازش استفاده می‌شه.
و اما soname چی هست؟ گوگل ایت!

هنر کراس کامپایل

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

Makefiles خالص

توی این makefileها معمولا کامپایلر از طریق متغیر CROSS_COMPILE تعیین میشه.
خوشبختانه اکثر پکیج‌ها و برنامه‌های مهم مثل کرنل لینوکس و BusyBox این جوری هستن.
برای کراس کامپایل کردن این برنامه‌ها فقط کافیه پیشوند تولچین رو به متغیر CROSS_COMPILE بدیم. دو مدل میشه این کار رو کرد: (اولش اون فایل رو سورس کنید.)

make CROSS_COMPILE=arm-richdad-linux-gnueabi-

یا

export CROSS_COMPILE= arm-richdad-linux-gnueabi-
make

 

البته برای کراس کامپایل کرنل یا کراس کامپایل BusyBox یه سری متغیرهای دیگه مثل ARCH هم باید ست بشن که توی فصل خودشون بشون میرسیم.

بیلد سیستم گنو که به Autotools شناخته میشه

احتمالا این چند خط واستون خیلی آشنا باشه، چند خطی که واسه خودم تا چند سال هیچ وقت جواب ندادن واسه هیچ برنامه‌ای!

$ ./configure
$ make
$ sudo make install

ین دستورات واسه زمانی هست که نمیخوایم کراس کامپایل کنیم و نیتیو داریم کامپایل میکنیم.
اما Autotools واسه کراس کامپایل کردن هم راه حل داره. یه سری متغیرها هست که هر کدوم لازم باشه باید ست کنیم:

CC: The C compiler command
CFLAGS: Additional C compiler flags
LDFLAGS: Additional linker flags; for example, if you have libraries in a non-standard directory <lib dir> , you would add it to the library search path by adding -L<lib dir>
LIBS: Contains a list of additional libraries to pass to the linker; for instance, -lm for the math library
CPPFLAGS: Contains C/C++ preprocessor flags; for example, you would add -I<include dir> to search for headers in a non-standard directory <include dir>
CPP: The C preprocessor to use

را برای *کراس کامپایل کنید SQLITEتمرین
*F1C100s

کراس کامپایل SQLite برای F1C100s

فرض میکنیم در فولدر F1C100s هستیم:

source at00exports.sh
cd project
wget https://www.sqlite.org/2021/sqlite-autoconf-3350200.tar.gz
tar xf sqlite-autoconf-3350200.tar.gz

خب تا اینجا که آسون بود ?
حالا میریم توی فولدر و کار اصلی رو شروع میکنیم:

cd sqlite-autoconf-3350200/
CC=$GCC ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for style of include used by make... GNU
checking for gcc... /home/at00/EmbeddedLinux/F1C100s/build-tools/at00toolchain/bin/arm-richdad-linux-gnueabi-gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... configure: error: in `/home/at00/EmbeddedLinux/F1C100s/project/sqlite-autoconf-3350200':
configure: error: cannot run C compiled programs.
If you meant to cross compile, use `--host'.
See `config.log' for more details

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

Build: is the computer that builds the package, which defaults to the current machine.
Host: is the computer the program will run on; for a native compile, this is left blank and it defaults to be the same computer as build. When you are cross compiling, set it to be the tuple of your toolchain.
Target: is the computer the program will generate code for; you would set this when building a cross compiler, for example.

این host در حقیقت چندتایی (tuple) تولچین هست.
به جز host یه چیز دیگه هم لازمه، محل نصب پیش فرض معمولا مسیر زیر هست:

<sysroot>/usr/local/*

ولی بهتره به این مسیر تغییرش بدیم (چرا؟):

<sysroot>/usr/*

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

CC=$GCC ./configure --host=arm-richdad-linux-gnueabi --prefix=/usr

خوشبختانه واسه من این دستور جواب داد واسه شما هم اگه تا الان مثل من پیش اومده باشین باید جواب بده.
و حالا بریم واسه make کردنش

make -j$(nproc)

سوال: -j$(nproc) چی هست و آیا باید باشد؟ جواب بایدی وجود ندارد، برای بقیه توضیحات گوگل ایت!
باورش سخته ولی make شد ?
خوب حالا بریم واسه نصب ولی قبلش یکم مرتب سازی انجام بدیم. ما الان می‌دونیم یه sysroot داریم و از قبل هم داخل فولدر پروژه مون یه فولدر ساخته بودیم به نام rootfs، خوب محتویات اون رو بریزیم توی این که دست به فایل‌های اصلی نزده باشیم، هرچند خروجی crosstool-NG به صورت Read Only هست.

cp -r ../../build-tools/at00toolchain/arm-richdad-linux-gnueabi/sysroot/* ../../rootfs/
chmod –R 777 ../../rootfs/*

خوب حالا بریم واسه نصب:

make DESTDIR=/home/at00/EmbeddedLinux/F1C100s/rootfs/ install

سوال: چه فایل‌هایی نصب شد؟
جواب: فایل‌های بسیاری از جمله این فایل که ببینید به درد چی می‌خوره!

usr/lib/pkgconfig/sqlite3.pc

سوال: آیا الان به راحتی می‌توان برنامه‌ای که از SQLite استفاده می‌کنه رو کراس کامپایل کرد با این دستور؟

$GCC -lsqlite3 sqlite-test.c -o sqlite-test

جواب: خیر، چون فایل‌های سرآیند و کتابخانه‌ها را در sysroot نصب نکردیم.
سوال: خوب چه باید کرد؟
جواب: -L و –I رو گوگل کنید!

هشدار

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

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

به جز minicom ابزار خاصی لازم نیست!
کرنل نویس‌ها کماکان از vi استفاده میکنن برای نوشتن کدهاشون!
با اطلاعاتی که الان دارید به راحتی می‌تونید تنظیمات لازم رو برای کیوت یا اکلیپس انجام بدین و از اونا برای نوشتن، بیلد کردن و دیپلوی کردن کدهاتون روی بردتون استفاده کنید.
من خودم از کیوت استفاده میکنم.
یکی دیگه از ابزارهایی که خوبه بدونید وجود داره gdb یا دیباگر GNU هست.
به پایان این فصل رسیدیم. در فصل بعد بیشتر وارد عمل می‌شیم و بوت لودر رو میریزیم روی بردمون تا آماده‌ش کنیم برای لینوکس.

 

پایان بخش نهم از فصل دوم

 

یه سری هم به نظرات این پایین بندازید، نظرات رو بخونید و اگر شما هم نظری دارید، مشارکت کنید!
همه آموزش های امبدد لینوکس

 

منبع:سیسوگ

مطلب قبلیآموزش STM32 با توابع LL قسمت سیزدهم: Timer-Input capture
مطلب بعدیآموزش ایجاد پروژه AVR جدید در نرم افزار Eclips

پاسخ دهید

لطفا نظر خود را وارد کنید!
لطفا نام خود را در اینجا وارد کنید