ورود

View Full Version : سوال: نصب کرنل



electro_fuzzy
یک شنبه 15 دی 1392, 21:53 عصر
سلام من مدتی هست که دارم تلاش میکنم که کرنل لینوکس رو نصب کنم البته تازه کارم میخواستم بپرسم که چطوری این کار رو انجام بدم و بدون شل لینوکس رو استفاده کنم .

prpe26
یک شنبه 15 دی 1392, 22:44 عصر
لینوکس (هسته) به تنهایی کار نمیکنه و نیاز به یک Userland داره (که معمولا GNU استفاده میشه) و مجموعه کرنل + یوزرلند = سیستم عامل کامل.

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

در مورد نصب هسته، شما میتونید یکی از هزاران توزیع رو انتخاب کنید (پیشنهاد من مینت یا اوبونتو هست : http://linuxmint.com , http://ubuntu.com ) و سعی کنید هسته اونها رو تغییر بدید و سفارشی سازی کنید.

electro_fuzzy
دوشنبه 16 دی 1392, 16:48 عصر
چطوری میشه به کرنل دسترسی داشت ؟ چطوری کامپایل میشه ؟ کامپایلر چی استفاده میشه ؟ کرنل با اسمبلی نوشته میشه ؟ ممنون

prpe26
دوشنبه 16 دی 1392, 20:19 عصر
بهتون توصیه میکنم یه مقدار مستقل عمل کنید و لینکی مثل این رو جدی بگیرید :

http://en.wikipedia.org/wiki/Linux

کرنل لینوکس کلا با C هست و in-line assembly هم درش یافت میشه.

ahmad24shargh
سه شنبه 17 دی 1392, 20:11 عصر
من آرچ لینوکس رو نصب دارم و هسته رو خودم کامپایل میکنم(از هسته کامپایل شده مخازن رسمی استفاده نمیکنم).هسته با مجموعه کامپایلر gcc کامپایل میشه(با هر کامپایلر c میشه کرنل رو کامپایل کرد)

برای سفارشی کردن هسته لینوکس معمولا یه واسط ncurses به نام menuconfig هست.گزینه های محدودی هستند که در دیستروهای متفاوت لینوکس اختصاصی هستند.اما بیشتر گزینه ها مشترک هستند.

تو آرچ لینوکس اسکریپتهای ساده bash به نام PKGBUILD برای کامپایل از سورس وجود داره که توسط دستور makepkg پکیج نصبی از سورس ایجاد میشه.

من از 2 هسته استفاده میکنم و هر بار که patch جدیدی از کرنل منتشر بشه به سرعت اسکریپتهای نصب از سورس در مخازن قرار میگیره به طوریکه گاهی ۲ بار در هفته هسته لینوکس رو سفارشی و کامپایل و نصب میکنم.اگر هر بار بخوام به صورت دستی و با واسط menuconfig گزینه های مد نظرمو تغییر بدم که یه روال کشنده میشه.
بعد از customize کردن یه فایل مخفی به نام config. تو پوشه سورس کرنل ایجاد میشه و بعد عمل کامپایل توسط make صورت میگیره.
برای اتوماتیک کردن تغییرات من صرفا از دستور sed برای تغییر در فایلهاس سورس از جمله config. که مربوط به پیکربندی کامپایل میشه استفاده میکنم.
من که از پردازنده ۴ هسته ای اینتل استفاده میکنم برای پروسه make این دو مورد رو تغییر دادم :




CFLAGS="-march=core2 -mtune=native"
MAKEFLAGS="-j4"


پچ های کرنل رو از kernel.org دانلود میکنم و اسکریپت کامپایل رو از ABS (مخزن رسمی آرچ) یا AUR (مخزن غیر رسمی کاربران) دانلود و اکسترکت میکنم.یه اسکریپت کوچولوی bash هم کل کار سفارشی سازی و کامپایل و نصب رو انجام میده. البته من فقط چند مورد رو تو فایل کانفیگ تغییر میدم اما مهم اتوماتیک کردن این فرآیند ملال آور و طولانیه.




#!/bin/bash
# ppi => prepare patch install
#

function Backup_orig()
{
main_file="$1"
grep -Eq "modified with ${SCRIPT_NAME}" ${main_file}
if [ $? -ne 0 ];then
echo -e "`date +"%A %d %B %Y %R"`\t INFO. Backing up '${main_file}' ... " | tee -a "$logfile" 2> /dev/null
\cp -f "${main_file}" "${main_file}.orig" &>/dev/null
[ "${main_file}" == "PKGBUILD" ] && export previously_patched=no
return 0
fi
echo -e "`date +"%A %d %B %Y %R"`\t WARNING. '${main_file}' previously patched with ${SCRIPT_NAME} ... patch ignored" | tee -a "$logfile" 2> /dev/null
[ "${main_file}" == "PKGBUILD" ] && export previously_patched=yes
return 1
}

function func_traping()
{
popd &>/dev/null
echo -e "`date +"%A %d %B %Y %R"`\t script stoped" | tee -a "$logfile" 2>/dev/null
echo | tee -a "$logfile" 2>/dev/null
return
}

trap func_traping EXIT

current_logged_user="`who | grep -v root | head -n 1 | cut -d " " -f1 | tr -d '\n'`" #${MAIL##*/}
export SCRIPT_NAME=$(basename $0)
mydir="$(cd `dirname $0` && pwd)"

let verbose=0 && export verbose
if [ ! -z "$1" ];then
if [ "$1" == "v" -o "$1" == "V" ];then
let verbose=1 && export verbose
shift
fi
[ ! -z "$1" ] && mydir="$1"
shift
fi
if [ ! -z "$1" -a "$1" == "v" -o "$1" == "V" ];then
let verbose=1 && export verbose
shift
fi

if [ ! -d "$mydir" ];then
echo -e "`date +"%A %d %B %Y %R"`\t FATAL ERROR, '$mydir' is not directory" | tee -a "$logfile" 2>/dev/null
exit 3
elif [ ! -w "$mydir" -o ! -r "$mydir" ];then
echo -e "`date +"%A %d %B %Y %R"`\t FATAL ERROR, read-write permission denied in '$mydir'" | tee -a "$logfile" 2>/dev/null
exit 3
else
work_folder="$mydir"
fi
logfile="${work_folder}/${SCRIPT_NAME%%.*}.log"
touch "$logfile" &>/dev/null
if [ ! -w "$logfile" ];then
logfile="${work_folder}/${SCRIPT_NAME%%.*}_$$.log"
touch "$logfile" &>/dev/null
echo | tee -a "$logfile" 2>/dev/null
echo -e "`date +"%A %d %B %Y %R"`\t script started" | tee -a "$logfile" 2>/dev/null
echo -e "`date +"%A %d %B %Y %R"`\t Error : ${work_folder}/${SCRIPT_NAME%%.*}.log No Writable !!!" | tee -a "$logfile" 2>/dev/null
echo -e "`date +"%A %d %B %Y %R"`\t changing log file to '${logfile}' " | tee -a "$logfile" 2>/dev/null
else
echo | tee -a "$logfile" 2>/dev/null
echo -e "`date +"%A %d %B %Y %R"`\t script started" | tee -a "$logfile" 2>/dev/null
fi

let bash_ver=${BASH_VERSINFO[0]} &>/dev/null
if [ "${bash_ver}" -lt 4 ];then
echo -e "`date +"%A %d %B %Y %R"`\t FATAL ERROR. Bash Shell Is Old Version And Not Compatible" | tee -a "$logfile" 2> /dev/null
exit 126
fi

unset OS_TYPE
OS_TYPE="`grep -Eio "arch" /etc/issue 2>/dev/null | tr "[:upper:]" "[:lower:]" 2>/dev/null | tr -d ' \n'`"
if [ "${OS_TYPE}" != "arch" ];then
echo -e "`date +"%A %d %B %Y %R"`\t FATAL ERROR. ${SCRIPT_NAME} only designed for Arch and Archers !!!" | tee -a "$logfile" 2> /dev/null
exit 127
fi

pushd "$work_folder" &>/dev/null

chown $current_logged_user "$logfile" &>/dev/null
if [ ! -f "./PKGBUILD" ];then
echo -e "`date +"%A %d %B %Y %R"`\t FATAL ERROR, PKGBUILD not found in `pwd`" | tee -a "$logfile" 2>/dev/null
echo -e "`date +"%A %d %B %Y %R"`\t FATAL ERROR, ${SCRIPT_NAME} must be places in source folder" | tee -a "$logfile" 2>/dev/null
exit 1
fi

echo -e "`date +"%A %d %B %Y %R"`\t INFO, extracting variable from PKGBUILD script ... " | tee -a "$logfile" 2>/dev/null
>/tmp/temp.$$
for var in $(grep -E '^[^ #]+=[^\(]+' PKGBUILD | sed -r 's:(.*)([ ]+#.*):\1:g');
do
echo "export $var &>/dev/null" | tee -a /tmp/temp.$$
done
. /tmp/temp.$$

if [ "$pkgname" == "linux-grsec" ];then
:
elif [ ! -z "$pkgbase" -a -z "$_kernelname" ];then
pkgname="$pkgbase"
else
echo -e "`date +"%A %d %B %Y %R"`\t FATAL ERROR, pkgname variable not set correctly" | tee -a "$logfile" 2>/dev/null
exit 2
fi

for i in "${pkgname}.install" "${pkgname}.preset";
do
if [ ! -f "./${i}" ];then
echo -e "`date +"%A %d %B %Y %R"`\t FATAL ERROR, ${SCRIPT_NAME} must be places in ${pkgname} folder" | tee -a "$logfile" 2>/dev/null
exit 1
fi
done

checksum_algorithm="$(grep -Eio '^.+[0-9]+sums=' PKGBUILD | grep -Eo '^.+[0-9]+')"
declare -a sourcefiles
declare -a checksums
sourcefiles=($(grep -A 20 -E 'source=[^)]+' PKGBUILD | grep -B 20 -m 1 -E '\)' | tr '()' '\n' | sed /source=/d | sed -r 's/^(\t| +)(.*)/\2/g' | sed -r /^#/d | sed -r "s/' '/'\n'/g" | sed -r 's/" "/"\n"/g' | tr -d '"' | tr -d "'"))
checksums=($(grep -A 20 -E '.*sums=[^)]+' PKGBUILD | grep -B 20 -m 1 -E '\)' | tr '()' '\n' | sed -r /sums=/d | sed -r 's/^(\t| +)(.*)/\2/g' | tr -d '"' | tr -d "'"))
let j=0
echo -e "`date +"%A %d %B %Y %R"`\t INFO, ${#sourcefiles[@]} sourcefiles with ${checksum_algorithm} algorithm ... " | tee -a "$logfile" 2>/dev/null
for files in ${sourcefiles[@]};
do
if [[ "${files}" =~ .*\.preset ]];then
offset_of_preset=$j
checksum_of_preset="${checksums[$j]}"
elif [[ "${files}" == "sysctl.conf" ]];then
offset_of_sysctl=$j
checksum_of_sysctl="${checksums[$j]}"
fi
let j++
done

#backup original file
Backup_orig "${pkgname}.preset"
if [ $? -eq 0 ];then
# Remove fallback preset from ${pkgname}.preset
echo -e "`date +"%A %d %B %Y %R"`\t INFO, Remove fallback preset from ${pkgname}.preset ... " | tee -a "$logfile" 2>/dev/null
sed -ri "s:(.+)( 'fallback'\))$:#modified with ${SCRIPT_NAME}\n#value before change \: \1\2\n\1\):g" ${pkgname}.preset
echo -e "`date +"%A %d %B %Y %R"`\t INFO, checksum calculation of ${pkgname}.preset with ${checksum_algorithm}sum ... " | tee -a "$logfile" 2>/dev/null
temp_checksum="$(${checksum_algorithm}sum ${pkgname}.preset 2>/dev/null | cut -d ' ' -f 1 2>/dev/null)"
if [ -z "${temp_checksum}" ];then
echo -e "`date +"%A %d %B %Y %R"`\t ERROR, error in checksum calculation" | tee -a "$logfile" 2>/dev/null
echo -e "`date +"%A %d %B %Y %R"`\t ERROR, checksum algorithm = '${checksum_algorithm}','${checksum_algorithm}sum' exist in PATH???" | tee -a "$logfile" 2>/dev/null
exit 3
fi
fi

#backup original file
Backup_orig PKGBUILD
if [ $? -eq 0 ];then
# update checksum
echo -e "`date +"%A %d %B %Y %R"`\t INFO, update checksum of ${pkgname}.preset in PKGBUILD ... " | tee -a "$logfile" 2>/dev/null
sed -ri "s:(.+)(${checksum_of_preset})(.*):#modified with ${SCRIPT_NAME}\n#value before change \: \1\2\3\n\1${temp_checksum}\2:g" PKGBUILD
fi

if [ "$pkgname" == "linux-grsec" -a -f "./sysctl.conf" ];then
#backup original file
Backup_orig sysctl.conf
if [ $? -eq 0 ];then
# Edit & customize sysctl.conf

#set kernel.grsecurity.tpe = 0 for firefox,wine,kde,...
echo -e "`date +"%A %d %B %Y %R"`\t INFO, patching sysctl.conf ... " | tee -a "$logfile" 2>/dev/null
sed -ri "s:(#?kernel.grsecurity.tpe = [0-1]?):\n#modified with ${SCRIPT_NAME}\n#value before change \: \1\nkernel.grsecurity.tpe = 0\n:g" sysctl.conf

#set kernel.grsecurity.disable_priv_io = 0 #you must compile with diabled priv_io if using non kms video driver
#sed -ri "s:(#?kernel.grsecurity.disable_priv_io = [0-1]?):\n#modified with ${SCRIPT_NAME}\n#value before change \: \1\nkernel.grsecurity.disable_priv_io = 0\n:g" sysctl.conf

#set kernel.grsecurity.timechange_logging = 0
#sed -ri "s:(#?kernel.grsecurity.timechange_logging = [0-1]?):\n#modified with ${SCRIPT_NAME}\n#value before change \: \1\nkernel.grsecurity.timechange_logging = 0\n:g" sysctl.conf

#Enable hotplug usb in standalone workstation environment
sed -ri "s:(#?kernel.grsecurity.deny_new_usb = [0-1]?):\n#modified with ${SCRIPT_NAME}\n#value before change \: \1\nkernel.grsecurity.deny_new_usb = 0\n:g" sysctl.conf

# Remove Tab And Spaces located before at EOl character
sed -ri 's:(.*)(=[ ]*[0-9]+)(.+):\1\2:g' sysctl.conf

unset temp_checksum
echo -e "`date +"%A %d %B %Y %R"`\t INFO, checksum calculation of sysctl.conf with ${checksum_algorithm}sum ... " | tee -a "$logfile" 2>/dev/null
temp_checksum="$(${checksum_algorithm}sum sysctl.conf 2>/dev/null | cut -d ' ' -f 1 2>/dev/null)"
if [ -z "${temp_checksum}" ];then
echo -e "`date +"%A %d %B %Y %R"`\t ERROR, error in checksum calculation" | tee -a "$logfile" 2>/dev/null
echo -e "`date +"%A %d %B %Y %R"`\t ERROR, checksum algorithm = '${checksum_algorithm}','${checksum_algorithm}sum' exist in PATH???" | tee -a "$logfile" 2>/dev/null
exit 3
fi

#update checksums
echo -e "`date +"%A %d %B %Y %R"`\t INFO, update checksum of sysctl.conf in PKGBUILD ... " | tee -a "$logfile" 2>/dev/null
sed -ri "s:(.+)(${checksum_of_sysctl})(.*):#modified with ${SCRIPT_NAME}\n#value before change \: \1\2\3\n\1${temp_checksum}\2:g" PKGBUILD
fi
fi

#s با توجه به اینکه سیستم من پردازنده ۴ هسته ای داره برخی تغییرات تو کانفیگ کرنل ایجاد میکنم
#s ضمنا فرکانس کلاک رو به 100 هزار تقلیل دادم. برنامه هایی که نیاز به مقدار بالاتر دارند در زمان اجرا میتونند اونو تنظیم کنند.
#s الگوریتم فشرده سازی کرنل رو هم از gz به xz تغییر دادم.
#s حافظه بافر log کرنل رو هم از 19 به 20 تغغیر دادم (از 512 کیلوبایت به 1024 کیلوبایت)
#s شما میتونید کلا این دستور sed رو کامنتگذاری کنید تا اجرا نشه یا بنا به نیاز خودتون تغییر بدید.
#Some customization in PKGBUILD
if [ "${previously_patched}" != "yes" ];then
echo -e "`date +"%A %d %B %Y %R"`\t INFO, Some customization in PKGBUILD ... " | tee -a "$logfile" 2>/dev/null
sed -ri "s:(.*yes \"\" \| make config.*):\1\n\n################################## ##########################\n#modified with ${SCRIPT_NAME}\n if [ \"\${pkgname}\" == \"linux-grsec\" ]; then \n \tsed -i 's/CONFIG_GRKERNSEC_TIME=y/# CONFIG_GRKERNSEC_TIME is not set/g' ./.config\n \tsed -i 's/CONFIG_GRKERNSEC_IO=y/# CONFIG_GRKERNSEC_IO is not set/g' ./.config\n fi\n sed -i 's/#define DEFAULT_CONSOLE_LOGLEVEL 7/#define DEFAULT_CONSOLE_LOGLEVEL 4/' ./kernel/printk/printk.c\n sed -i 's/CONFIG_KERNEL_GZIP=y/# CONFIG_KERNEL_GZIP is not set/g' ./.config\n sed -ri 's/#[ ]*CONFIG_KERNEL_XZ is not set/CONFIG_KERNEL_XZ=y/g' ./.config\n sed -ri 's/CONFIG_LOG_BUF_SHIFT=[0-9]+/CONFIG_LOG_BUF_SHIFT=20/g' ./.config\n sed -ri 's/#[ ]*CONFIG_MCORE2 is not set/CONFIG_MCORE2=y/g' ./.config\n sed -ri 's/CONFIG_GENERIC_CPU=y/# CONFIG_GENERIC_CPU is not set\\\nCONFIG_X86_INTEL_USERCOPY=y\\\nCONFIG_X86_U SE_PPRO_CHECKSUM=y\\\nCONFIG_X86_P6_NOP=y/g' ./.config\n sed -ri 's/^(CONFIG_HZ_[0-9][0-9][0-9][0-9]?)=y/# \\\1 is not set/g' ./.config\n sed -ri 's/^#[ ]*CONFIG_HZ_100 is not set.*/CONFIG_HZ_100=y/g' ./.config\n sed -ri 's/^CONFIG_HZ=.*/CONFIG_HZ=100/g' ./.config\n #sed -ri 's/CONFIG_FAT_DEFAULT_CODEPAGE=[0-9]+/CONFIG_FAT_DEFAULT_CODEPAGE=864/g' ./.config\n #sed -ri 's/CONFIG_FAT_DEFAULT_IOCHARSET=.*/CONFIG_FAT_DEFAULT_IOCHARSET=\"utf8\"/g' ./.config\n######################################### ###################\n:g" PKGBUILD
fi

#Verbose make ouput if verbose is sets
if [ "${previously_patched}" != "yes" -a ${verbose} -eq 1 ];then
echo -e "`date +"%A %d %B %Y %R"`\t INFO, change PKGBUILD to verbose make procedure ... " | tee -a "$logfile" 2>/dev/null
sed -ri "s|(^.*make .\{MAKEFLAGS\} )(.*)|\n########################################## ##################\n#modified with ${SCRIPT_NAME}\n#Added V=1 for debugging make procedure\n\1V=1 \2\n############################################## ##############\n|g" PKGBUILD
fi

# using Temp folder if greather than 2500 MB
if [ $(echo "`pwd`" | sed -r 's:(/[^/]+)(.*):\1:g' 2>/dev/null) != "/tmp" ];then
unset temp_avail_size
let temp_avail_size=$(df -h -B M | grep '/tmp' | tr -s ' ' | cut -d ' ' -f 4 | sed -r 's:([0-9]+)(.*):\1:g') 2> /dev/null
if [ $? -eq 0 ];then
if [ ${temp_avail_size} -ge 2500 ];then
echo -e "`date +"%A %d %B %Y %R"`\t INFO, Available Temp size is ${temp_avail_size}" | tee -a "$logfile" 2>/dev/null
echo -e "`date +"%A %d %B %Y %R"`\t INFO, copy '$(basename ${work_folder})' to tmp for compiling ... " | tee -a "$logfile" 2>/dev/null
\cp -R ${work_folder} /tmp/ && cd /tmp/$(basename ${work_folder})
fi
fi
fi

if [ $UID == 0 ];then
echo -e "`date +"%A %d %B %Y %R"`\t NOTICE, makepkg with root privilage ..." | tee -a "$logfile" 2>/dev/null
makepkg --asroot --noconfirm -f
ERRORCODE=$?
else
echo -e "`date +"%A %d %B %Y %R"`\t NOTICE, makepkg with regular privilage ..." | tee -a "$logfile" 2>/dev/null
makepkg --noconfirm -f
ERRORCODE=$?
fi

if [ $ERRORCODE -ne 0 ];then
echo -e "`date +"%A %d %B %Y %R"`\t FATAL ERROR, error in makepkg" | tee -a "$logfile" 2>/dev/null
echo -e "`date +"%A %d %B %Y %R"`\t FATAL ERROR, please run ${SCRIPT_NAME} with v argument(verbose output for debugging)" | tee -a "$logfile" 2>/dev/null
exit 4
fi

echo -e "`date +"%A %d %B %Y %R"`\t Granting permission for installing packages ... \n" | tee -a "$logfile" 2>/dev/null
sudo -v
if [ $? -ne 0 ];then
while true;
do
#s آیا کاربر ریشه است؟در غیر اینصورت اسکریپت با کاربر ریشه اجرا می‌شود
#s در صورتیکه آپشن -a تنظیم شود دستور su وارد loop بی انتها می‌شود
if [ $UID -ne 0 ];then
if [[ -z "$echoed" ]];then
echo "$USER: You must login with root password to continue"
echo "Please Enter Password Of Root Admin Below"
export echoed=yes
fi
su -m
error_code=$?
case "$error_code" in
0) break;;
125) echo -e "\t\tPassword Incorrect,Try Again ..."; echo;;
*) echo "Error Code $error_code"; exit 125;;
esac
else
break
fi
done
fi
[ $UID -eq 0 ] && sudoer='' || sudoer="sudo "

#linux-docs-3.12.6-1-x86_64.pkg.tar.xz linux-headers-3.12.6-1-x86_64.pkg.tar.xz linux-3.12.6-1-x86_64.pkg.tar.xz

if [ -f "./${pkgname}-docs-${pkgver}-${pkgrel}-$(uname -m).pkg.tar.xz" ];then
echo -e "`date +"%A %d %B %Y %R"`\t Installing \"./${pkgname}-docs-${pkgver}-${pkgrel}-$(uname -m).pkg.tar.xz\" ... \n" | tee -a "$logfile" 2>/dev/null
${sudoer}pacman -U --noconfirm "./${pkgname}-docs-${pkgver}-${pkgrel}-$(uname -m).pkg.tar.xz"
fi
if [ -f "./${pkgname}-headers-${pkgver}-${pkgrel}-$(uname -m).pkg.tar.xz" ];then
echo -e "`date +"%A %d %B %Y %R"`\t Installing \"./${pkgname}-headers-${pkgver}-${pkgrel}-$(uname -m).pkg.tar.xz\" ... \n" | tee -a "$logfile" 2>/dev/null
${sudoer}pacman -U --noconfirm "./${pkgname}-headers-${pkgver}-${pkgrel}-$(uname -m).pkg.tar.xz"
fi
if [ -f "./${pkgname}-${pkgver}-${pkgrel}-$(uname -m).pkg.tar.xz" ];then
echo -e "`date +"%A %d %B %Y %R"`\t Installing \"./${pkgname}-${pkgver}-${pkgrel}-$(uname -m).pkg.tar.xz\" ... \n" | tee -a "$logfile" 2>/dev/null
${sudoer}pacman -U --noconfirm "./${pkgname}-${pkgver}-${pkgrel}-$(uname -m).pkg.tar.xz"
fi

#Cleaning up src & pkg folders; use -c in makepkg instead
\rm -Rf src/ pkg/ &>/dev/null

# update grub menu
#${sudoer}grub-mkconfig -o /boot/grub/grub.cfg

[ -f /etc/sysctl.d/05-grsecurity.conf.pacnew ] && ${sudoer}mv /etc/sysctl.d/05-grsecurity.conf.pacnew /etc/sysctl.d/05-grsecurity.conf

prpe26
سه شنبه 17 دی 1392, 20:50 عصر
MAKEPKG ها خوب ولی زیادی پیچیده هستند.

به نظرم LFS میتونه کمک خوبی باشه :

http://linuxfromscratch.org