【筆記】構建 Linux v1.1

2014-05-26 21:21:38
構建Linux 編譯Linux BeagleBone Black

14年即將畢業(yè)時構建的


與上一版本1相比,我重新編譯了,整理了下。
既然可以連HDMI顯示器,那我研究下Wayland。以后再研究網絡。

說明

我構建的目標平臺為BeagleBone Black
交叉編譯工具為Sourcery CodeBenchLite

要構建Linux,很簡單,只有3個部分,

  1. bootloader,即啟動引導程序,我選擇U-Boot。
  2. Linux內核。
  3. 應用程序。

我這里構建的目標是可編譯C程序。
我還沒研究是什么決定了32位和64位。

我主要的資料,

  • Running Linux
    介紹Linux的書,這才叫入門級,了解下Linux的思想即可,書的內容可能有些過時,
    這本書不是介紹怎么使用Linux的。如果想知道怎么使用Linux,
    可看看Linux Pocket Guide,很薄。
    鳥哥的書也不錯,感覺挺詳細的,好于大部分書,我沒看。
    我連shell腳本都不會寫呢,很多命令沒用過,這與構建Linux關系不大。

  • Building Embedded Linux Systems
    教構建嵌入式Linux的,了解下思想即可。

  • Linux From Scratch
    教構建各種Linux的網站,最關鍵的是網站給出了Linux由哪些應用程序構成。
    我沒有用網站中的方式,sed那種命令不會。也是了解下思想即可。

If you can’t explain it simply, you don’t understand it well enough.
--Albert Einstein

準備SD卡

BeagleBone Black有4種啟動方式,我選擇用SD卡。
將SD卡插到電腦中,在我的系統(tǒng)中被識別為/dev/sdb。

分區(qū):

# fdisk /dev/sdb

用法很簡單,輸入'm',就可得到幫助。
第一個分區(qū)64M,類型為FAT32 (LBA),加上啟動標記。
第二個分區(qū)為余下的全部,類型默認為Linux,不必改。

參考過程是這樣的,
輸入'o',新建一個空DOS分區(qū)表,這會清除所有分區(qū)。
輸入'p',會列出分區(qū)列表,此時應該沒有。
輸入'n'來添加新分區(qū),直接'enter',接受默認為主分區(qū),'enter'接受默認為第一分區(qū),
'enter'接受默認的開始扇區(qū),輸入'+64M',設置分區(qū)大小為64M。
輸入't',來改變分區(qū)類型,自動選擇了第一個分區(qū),輸入l可列出所有分區(qū)列表的代碼,
輸入'c'選擇W95 FAT32(LBA)。
輸入'a',在第一分區(qū)設置可啟動標記。
輸入'n','enter'主分區(qū),'enter'第二個,'enter'起始扇區(qū),'enter'結束扇區(qū)。
輸入'w',將改動寫入分區(qū)表。

格式化:

# mkfs.vfat -F 32 /dev/sdb1
# mkfs.ext4 /dev/sdb2

第一個分區(qū)用來放U-Boot。
第二個分區(qū)用來放Linux系統(tǒng)。

sdb2被格式化后,里面自動有個lost+found,文件系統(tǒng)的結構中正好有一條:

/lost+found: Filesystem-specific recoverable data

文件系統(tǒng)目錄結構

因為感覺Linux系統(tǒng)比較亂,
嘗試改變了下目錄結構。
和我一樣想法的不止我一個,例如GoboLinux

/
/data/             #存放數據,看看下面的軟鏈接就知道了。
/lost+found
/mount/            #掛載點,就是傳統(tǒng)的mnt。
/program/          #存放程序,Linux內核也在里面。
/user/             #用戶,就是傳統(tǒng)的home。
/dev/

dev本來應該是下面那樣的軟鏈接,但那樣的話不能在ttyO0登陸,
不過倒是可以在tty1登陸,也就是通過HDMI連接顯示器的時候。
為了兼容,以下是一些額外的軟鏈接,注意并沒有dev。

/bin -> /data/index/bin       ;index中的都是軟連接,指向program中相應位置。
/dev -> /data/device          
/etc -> /data/configuration   ;有些程序要在這里找配置文件。
/lib -> /data/index/lib
/proc -> /data/process
/run -> /data/run
/sbin -> /data/index/bin
/sys -> /data/system
/tmp -> /data/temporary
/var -> /data/variable

/usr/
/usr/include -> /data/index/include
/usr/lib -> /data/index/lib

/usr/share/
/usr/share/info -> /data/index/info
/usr/share/man -> /data/index/man

便簽

export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
export PKG_CONFIG_LIBDIR=/home/spy/Work/data/index/lib/pkgconfig
export PKG_CONFIG_SYSROOT_DIR=/home/spy/Work
--prefix=/program/
--oldincludedir=/program//oldinclude
--build=x86_64-unknown-linux-gnu
--host=arm-none-linux-gnueabi
DESTDIR=/home/spy/Work
chown -R 0:0
chgrp -v tty /program/util-linux/bin/wall
chown -R spy:users

以可讀寫重新掛載根文件系統(tǒng)

mount -n -o remount,rw /

放到交叉編譯器搜索庫中的程序庫
linux-pam,ncurses,libcap,gdbm

coreutils與util-linux重復的命令。
kill

shadow與util-linux重復的命令。
{login,nologin,su}

shadow與coreutils重復的命令。
groups

編譯軟件

U-Boot

2分鐘 CPU 1.86GHz;內存2G,DDR2,單條1G。

$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ export CROSS_COMPILE=arm-none-linux-gnueabi-
$ cd /home/spy/Work/sources/u-boot/u-boot-2014.04
$ make O=/home/spy/Work/program/u-boot distclean
$ make O=/home/spy/Work/program/u-boot am335x_boneblack_config
$ make O=/home/spy/Work/program/u-boot all

源碼中正好有am335x_boneblack這個配置文件,對應我的開發(fā)板,
想知道可用的配置文件看README吧,它會告訴你到另一個文件boards.cfg中找。

AM335x U-Boot User's Guide
TI的wiki,看“Two stage U-Boot design”讓你了解MLO和u-boot.img是什么。
大概是AM335X芯片中的程序較小,只為了4種啟動方式初始化,
然后找到MLO,運行MLO進一步初始化,如DDR3內存。
MLO最后找到u-boot.img,運行之。u-boot.img這個名字應該是在MLO的>代碼中指定的。
提示:TI的StarterWare中的2個文件叫MLO和app。

編譯完后,現(xiàn)在就可以找找成就感了,

  1. 將MLO和u-boot.img復制到SD卡的第一個分區(qū)里;
  2. 將串口調試用的線與計算機相連,啟動串口調試程序,如Putty
  3. 將SD卡插入開發(fā)板,保持按下板子上的啟動選擇鍵,插上電源,板子會從SD卡啟動,
  4. 可以松開啟動選擇鍵了。

Putty的窗口上會打印一些信息,你會看到一個1秒的倒計時,
然后U-Boot會運行環(huán)境變量中已經設置好的一些列命令,比如將Linux內核載入內存,
但此時還沒有內核文件,U-Boot會停留在它自己的命令行中,
你可以輸入命令,如reset,這會讓板子重啟,
倒計時的時候按下計算機上的任意鍵,U-Boot就不會運行環(huán)境變量中的命令了,
可玩一玩下面的演示。

給出U-Boot中的一些演示,輸入help可顯示所有命令。
help后接命令,可顯示該命令的幫助。如

help help
U-Boot# mmc rescan
U-Boot# mmc list
OMAP SD/MMC: 0
 OMAP SD/MMC: 1
U-Boot# mmc dev
mmc0 is current device
U-Boot# mmc part

Partition Map for MMC device 0  --   Partition Type: DOS

Part    Start Sector    Num Sectors     UUID            Type
  1     2048            131072          29942d7e-01     0c Boot
  2     133120          15390720        29942d7e-02     83
U-Boot# ls mmc 0:1
   100688   mlo
   308232   u-boot.img
      510   uenv.txt

3 file(s), 0 dir(s)

U-Boot# ls mmc 0:2
<DIR>       4096 .
<DIR>       4096 ..
<SYM>          7 bin
<DIR>       4096 boot
<DIR>       4096 dev
<DIR>       4096 etc
<DIR>       4096 home
<SYM>          7 lib
<DIR>       4096 lost+found
<DIR>       4096 mnt
<DIR>       4096 proc
<DIR>       4096 run
<SYM>          7 sbin
<DIR>       4096 sys
<DIR>       4096 tmp
<DIR>       4096 usr
<DIR>       4096 var
U-Boot# mmcinfo
Device: OMAP SD/MMC
Manufacturer ID: 3
OEM: 5344
Name: SU08G
Tran Speed: 50000000
Rd Block Len: 512
SD version 3.0
High Capacity: Yes
Capacity: 7.4 GiB
Bus Width: 4-bit
U-Boot# mmc dev 1
mmc1(part 0) is current device
U-Boot# mmcinfo
Device: OMAP SD/MMC
Manufacturer ID: fe
OEM: 14e
Name: MMC02
Tran Speed: 52000000
Rd Block Len: 512
MMC version 4.41
High Capacity: No
Capacity: 1.8 GiB
Bus Width: 4-bit
U-Boot# mmc dev 0
mmc0 is current device
U-Boot#

fatls, ext4ls 也可以顯示文件,但對應某種文件系統(tǒng)。

Linux

26 + 53

內核配置文件我在開發(fā)板的GitHub找的,
復制一份名字改“.config”放到O指定的目錄中。
這樣就可以用make oldconfig了。
如果要修改的話,要注意systemd對內核的配置是有要求的,我并沒有改。

編譯Linux內核的時候,提示我的系統(tǒng)中缺少bc,用你的包管理器安上就好了。

$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ export CROSS_COMPILE=arm-none-linux-gnueabi-
$ export PATH=$PATH:/home/spy/Work/program/u-boot/tools
$ cd /home/spy/Work/sources/linux/linux-3.14.4
$ make O=/home/spy/Work/program/linux ARCH=arm help
$ make O=/home/spy/Work/program/linux ARCH=arm oldconfig
$ make O=/home/spy/Work/program/linux ARCH=arm LOADADDR=0x80008000 uImage
$ make O=/home/spy/Work/program/linux ARCH=arm LOADADDR=0x80008000 dtbs
$ make O=/home/spy/Work/program/linux ARCH=arm LOADADDR=0x80008000 modules
$ make O=/home/spy/Work/program/linux ARCH=arm LOADADDR=0x80008000 INSTALL_MOD_PATH=/home/spy/Work/root/program/linux/modules modules_install
$ make O=/home/spy/Work/program/linux ARCH=arm LOADADDR=0x80008000 INSTALL_FW_PATH=/home/spy/Work/root/program/linux/firmware firmware_install
$ make O=/home/spy/Work/program/linux ARCH=arm LOADADDR=0x80008000 INSTALL_HDR_PATH=/home/spy/Work/root/program/linux/headers headers_install

make help是否指定ARCH,輸出內容是不同的。

uImage就是Linux內核,編譯時需要mkimage這個工具,編譯U-Boot的時候會生成那個工具,
所以我編譯內核之前將該目錄加到了PATH環(huán)境變量中。

需要指定“LOADADDR”,否則會有下面的問題。

  Kernel: arch/arm/boot/zImage is ready
multiple (or no) load addresses: 
This is incompatible with uImages
Specify LOADADDR on the commandline to build an uImage
  • dts --> device tree source
  • dtb --> device tree blob
  • dtbo --> device tree blob overlay
  • dtc --> device tree compile

沒研究為什么編譯設備樹是dtbs,是在make help的幫助中看到的。

內核的配置中指定了很多把驅動編譯成模塊的,這部分需要make modules來單獨編譯。

編譯完成后,可在輸出文件夾的arch/arm/boot找到zImage, uImage和dts子文件夾,dts里面有am335x-boneblack.dtb。zImage也是內核,也可以用,但我用的uImage。

最后那三個安裝目錄自己選個更好的吧。

  • modules會安在lib/moduleslib/firmware2個文件夾中。
  DEPMOD  3.14.4
depmod: ERROR: Module 'hci_vhci' has devname (vhci) but lacks major and minor information. Ignoring.

安裝modules的時候,可能會提示depmod出問題,據說正常,那不是處理交叉編譯的模塊的。
但我還是看到了depmod后應該出現(xiàn)的modules.dep文件。
depmod是用來構建模塊依賴關系的,目的是,當用insmod裝載某模塊的時候,可能會失敗,
因為這個模塊依賴的其他模塊還沒有裝入內核,depmod構建完依賴關系后,用另外一個命令裝載模塊,即可自動裝載模塊所依賴的其他模塊。

  • firmware也安在lib/firmware中,但與modules中的不同。我目前不知道firmware是干什么的。

  • headers還是需要安裝的,它就像glibc那樣,編譯程序時被調用。


下面可以驗證了。
將uImage文件,dts文件夾復制到SD卡第二個分區(qū)的/boot/里。
其實dts中應該只需am335x-boneblack.dtb。

啟動開發(fā)板前應該了解下U-Boot如何載入Linux。

U-Boot中最關鍵的環(huán)境變量

  • bootcmd: This variable defines a command string that is automatically executed when the initial countdown is not interrupted.
    This command is only executed when the variable bootdelay is also defined!
  • bootargs: The contents of this variable are passed to the Linux kernel as boot arguments (aka "command line").

U-Boot中最關鍵的命令

  • run - run commands in an environment variable

U-Boot啟動后會運行bootcmd里的命令,所以要研究的話,從bootcmd開始。

提示:我的研究在后面。現(xiàn)在可不必研究直接看我的處理。

編譯后的U-Boot是不能引導uImage的,通過printenv看U-Boot的環(huán)境變量,
可看到它找的是zImage,而且am335x-boneblack.dtb是在/boot/中找,不是/boot/dts/

為了符合我的要求,要修改環(huán)境變量,可以用editenv修改環(huán)境變量后saveenv。
但還是別這么做了,我不知道它把環(huán)境變量保存到哪里去了。我以為把MLO和u-boot.img換回原始的可以恢復默認的環(huán)境變量值,但不是這樣,把SD卡格式化后也沒用。
有可能是存到eMMC中了,我想盡各種辦法破壞eMMC的數據,用了
dd if=/dev/zero of=/dev/mmcblk1也不行。
除了mmcblk1還有個mmcblk1boot,可能是存到那里了,記著那個設備比較奇怪,沒有驗證。
最后用env default -a然后saveenv恢復默認了。

另一個方法是創(chuàng)建一個uEnv.txt文件,將它和MLO放到一起,內容如下。
該文件中的環(huán)境變量會覆蓋掉默認的環(huán)境變量。

bootdir=/program/linux/boot
bootfile=uImage
loadfdt=load mmc ${bootpart} ${fdtaddr} ${bootdir}/dts/${fdtfile}
mmcloados=run mmcargs; if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if run loadfdt; then bootm ${loadaddr} - ${fdtaddr}; else if test ${boot_fdt} = try; then bootz; else echo WARN: Cannot load the DT; fi; fi; else bootz; fi;
mmcroot=/dev/mmcblk0p2 rw
mmcargs=setenv bootargs console=${console} ${optargs} root=${mmcroot} rootfstype=${mmcrootfstype} init=/program/systemd/root/lib/systemd/systemd

一共7行,最后一行空白。

  • bootdir修改了內核存放的目錄。
  • bootfile修改了內核名字,
  • loadfdt中只是在目錄中加了“dts/”,
  • mmcloados主要是把bootz改成bootm。
  • mmcroot把只讀改成了讀寫,原因是systemd啟動后會創(chuàng)建一個machine-id到/etc中。也許有其他辦法,如/etc/fstab文件,但我為了簡單沒創(chuàng)建那個文件。
  • mmcargs只是在后面指定了init為systemd,也有其他方法,如init為指向systemd的軟鏈接。

啟動BeagleBone Black,待內核啟動后會打印很多信息,最后你將目睹“kernel panic”,
這是因為我們目前并沒有init程序,為了找到成就感,
你可以編譯下面靜態(tài)鏈接的“Hello world!”,放到某個目錄中,
然后在U-Boot的mmcargs變量中把init指定為那個hello。

hello.c

#include <stdio.h>

int main(int argc, char *argv)
{
  printf("Hello world!\n");
  sleep(999999999);
}
$ arm-none-linux-gnueabi-gcc -o hello -static hello.c

再次啟動,最后你看到的將是"Hello world!"。


我分析了U-Boot的引導過程,如下,再往下是我的演示。

gpio set 53        # 這個是點亮LED燈的,其實并沒有這個,是我在其他的U-Boot中看到的。
i2c mw 0x24 1 0x3e # 這個也沒有,不知干什么的。
mmc dev 0          # 將設備切換到'0',即SD卡,其實一開始就是'0',eMMC是'1'。
mmc rescan         # 應該是檢測設備是否存在吧。

gpio set 54
load mmc 0 0x80200000 uEnv.txt
env import -t 0x80200000 $filesize # 這2步是導入環(huán)境變量,filesize這個變量沒找到。

gpio set 55
load mmc 0:2 0x80200000 /boot/uImage

gpio set 56
load mmc 0:2 0x80F80000 /boot/dts/am335x-boneblack.dtb

setenv bootargs console=ttyO0,115200n8 ${optargs} root=/dev/mmcblk0p2 rw rootfstype=ext4 rootwait init=/usr/lib/systemd/systemd
bootm 0x80200000 - 0x80F80000

# optargs這個環(huán)境變量也沒找到,在其他U-Boot中發(fā)現(xiàn)是quiet,
# 作用是減少了內核打印的信息,systemd打印的信息也少了。
U-Boot# mmc dev 0
mmc0 is current device
U-Boot# mmc rescan
U-Boot# load mmc 0:2 0x80200000 /boot/uImage
3894896 bytes read in 237 ms (15.7 MiB/s)
U-Boot# load mmc 0:2 0x80F80000 /boot/dts/am335x-boneblack.dtb
17911 bytes read in 213 ms (82 KiB/s)
U-Boot# setenv bootargs console=ttyO0,115200n8 root=/dev/mmcblk0p2 rw rootfstype=ext4 rootwait init=/usr/lib/systemd/systemd
U-Boot# bootm 0x80200000 - 0x80F80000
## Booting kernel from Legacy Image at 80200000 ...
   Image Name:   Linux-3.13.5
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    3894832 Bytes = 3.7 MiB
   Load Address: 80008000
   Entry Point:  80008000
   Verifying Checksum ... OK
## Flattened Device Tree blob at 80f80000
   Booting using the fdt blob at 0x80f80000
   Loading Kernel Image ... OK
   Using Device Tree in place at 80f80000, end 80f875f6

Starting kernel ...

[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Initializing cgroup subsys cpuset
[    0.000000] Initializing cgroup subsys cpu
[    0.000000] Initializing cgroup subsys cpuacct
[    0.000000] Linux version 3.13.5 (spy@alien) (gcc version 4.8.1 (Sourcery CodeBench Lite 2013.11-33) ) #1 SMP Sat Mar 8 20:26:55 UTC 2014

我并沒有導入uEnv.txt,它是下面這個樣子的。

U-Boot# load mmc 0 0x80200000 uEnv.txt
reading uEnv.txt
510 bytes read in 4 ms (124 KiB/s)
U-Boot# env import -t 0x80200000
## Info: input data size = 966 = 0x3C6

下面就是應用程序了,可根據我的提示自行安排順序,我曾經的順序不是這樣的。
主要的過程就是glibc,bash,coreutils,util-linux,systemd,shadow,
這些中間的都是被依賴的程序。
bash需要libgcc_s.so.1,它位于gcc中,但編譯gcc時間較長,gcc還依賴5個程序。
迫不及待驗證編譯結果的話可以先把交叉編譯器中的庫復制到開發(fā)板系統(tǒng)中,我當初就那么做的。

  • glibc是程序庫,幾乎動態(tài)鏈接的程序都要用到了,"Hello world"中的printf函數都需要。
  • bash是個shell,即命令解釋器,提供了人與計算機交互的界面。
  • coreutils里有很多常用命令,如'ls'。
  • util-linux也是有很多命令,如mount,login,fdisk。
  • systemd是個init程序。
  • shadow是和登陸相關的,主要是把'/etc/passwd'文件里的密碼變成“x”,
    里面有l(wèi)ogin,passwd,useradd等命令。

其實系統(tǒng)啟動后的第一個程序是systemd,但它的文檔較少,不了解是怎么工作的,所以先保證其他的能工作,再研究。

至于怎么編譯,源碼中會有README,INSTALL等文檔。


環(huán)境變量的設置。

$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ export PKG_CONFIG_LIBDIR=/home/spy/Work/data/index/lib/pkgconfig
$ export PKG_CONFIG_SYSROOT_DIR=/home/spy/Work

有些程序的編譯需要pkg-config這個程序,這個程序根據系統(tǒng)程序庫中的.pc文件,生成編譯時的參數。
我這樣設置是為了找到我們自己編譯的,而不是/usr/lib/pkgconfig中的。
PKG_CONFIG_LIBDIR覆蓋了pkg-config默認的搜索路徑。
PKG_CONFIG_SYSROOT_DIR是為了交叉編譯準備的,它的值會加到參數前。

glibc

18
/usr/local
->
<- bash, //這2個依賴和被依賴的,僅供參考,肯定不全的,下面也一樣。

$ cd /home/spy/Work/sources/glibc/build
$ ../glibc-2.19/configure --prefix=/program/glibc --oldincludedir=/program/glibc/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install install_root=/home/spy/Work

源碼中并沒有makefile文件,這需要運行configure來生成。
通過configure --help查看可用的選項。

  • prefix為安裝目錄;

  • oldincludedir,不太清楚,根本沒用上;

  • build和host用來指定系統(tǒng)類型。可看看autoconf的手冊中“Specifying target triplets”。

  • build - 構建程序的系統(tǒng),在該系統(tǒng)中配置和編譯程序。

  • host - 構建后的程序運行在此系統(tǒng)中。

  • target - 編譯工具為此系統(tǒng)生成程序。

這個target,配置glibc不用指定,有的文檔中是這樣說的。

It's for use when building compiler tools, with --host being where they
will run, and --target what they'll produce code for.

也就是說,通常用在構建編譯工具的時候,舉個例子,

  • 如果你在你的x86_64計算機中編譯gcc,運行在你的x86_64系統(tǒng)中,讓gcc生成的程序也運行在x86_64中,
    這三個是這樣的(為了突出重點,我簡化了等號右邊):
    build=x86_64,host=x86_64,target=x86_64。
    在Arch Linux中運行pacman -S gcc安裝的就是這種(pacman是包管理器)。
  • 前2個條件不變,如果讓gcc生成的程序運行在arm中,就像我們要用的Sourcery CodeBench Lite,那么這三個是這樣的:
    build=x86_64,host=x86_64,target=arm
  • 第一個條件不變,如果讓gcc運行在arm中,生成的程序也運行在arm中,就像后面我們要編譯的,這三個是這樣的:
    build=x86_64,host=arm,target=arm

等號右邊的格式如下:

cpu-company-system

system可以有以下2種格式之一

  • os
  • kernel-os

查看源碼中的config.sub文件,能看到各部分可能的值。
運行configure的時候,如果沒指定的話,configure會用config.guess這個腳本猜出build的值。然后host默認等于build,target默認等于host。
config.guess通常和config.sub在一起,都可單獨運行的,有--help這個選項可用。

在我的系統(tǒng)中猜測出的值為x86_64-unknown-linux-gnu
在BeagleBone Black中,結果為armv7l-unknow-linux-gnueabihf
這個結果應該是不知道的,因為我是在BeagleBone Black已經可用的系統(tǒng)中運行的config.guess
而我們的系統(tǒng)還沒有構建出來呢,不可能運行config.guess。

那么我們如何確定host呢,難道要看config.sub?不必。
當build和host不同的時候,configure會啟用交叉編譯模式。
它會檢測以host值為前綴的編譯工具,如arm-none-linux-gnueabi-gcc,
然后使用這個帶前綴的gcc。所以我們的host指定為我們交叉編譯器中命令的前綴就好了。
我嘗試過了,如果host是“abcdefg”這種,大概會提示無效的值;
如果是“arm-none-linux-gnueabihf”這種有效的,
configure會檢測arm-none-linux-gnueabihf-gcc,他是找不到的。

既然build可以猜測出來,那是否還要指定呢,我開始就是沒指定,可以的。但是autoconf手冊中:

“For historical reasons, whenever you specify --host, be sure to specify --build > too; this will be fixed in the future.”

看來這個“future”已經到了,但我還是指定了。

我們編譯程序是用在其他的系統(tǒng)中,如果不指定install_root,它就要往prefix指定的目錄安了,
不要這樣,我的路徑還好,如果是/usr/lib/,那就破壞了你正使用的系統(tǒng),不過我用的是普通用戶,應該沒權限往那個目錄安。
有了install_root,就會安裝到/home/spy/Work/program/glibc,看看makefile文件就會明白原理。
那么把prefix指定為那個完整的目錄,不使用install_root行不行呢。最好別這樣。
構建完glibc,其中的ld.so并不是在/lib/或/usr/lib/中找程序庫,而是在glibc的庫被安裝到的目錄中找,即/program/glibc/lib
可見,這個prefix會記錄到生成的程序中,所以最好別讓目錄那么長,那么亂。

問題又來了,ld.so竟然不在/usr/lib/中找程序庫,這可是傳說中的默認目錄啊。
我的處理是在構建的系統(tǒng)中運行l(wèi)dconfig,在bash中說。

gmp

2
/usr/local
->
<- mpfr,mpc,isl,cloog,gcc

編譯這個的時候提示我缺少m4,安上。

$ cd /home/spy/Work/sources/gmp/build
$ ../gmp-6.0.0/configure --prefix=/program/gmp --oldincludedir=/program/gmp/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work

這個和下面的4個都是為gcc服務的。
這里的安裝目錄用的是DESTDIR,看看源代碼里的文檔吧。

mpfr

2
/usr/local
-> gmp,
<- mpc,gcc

$ cd /home/spy/Work/sources/mpfr/build
$ ../mpfr-3.1.2/configure --prefix=/program/mpfr --oldincludedir=/program/mpfr/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi --with-gmp=/home/spy/Work/program/gmp
$ make
$ make install DESTDIR=/home/spy/Work

修改lib/libmpfr.la

# Libraries that this one depends upon.
dependency_libs=' -L/home/spy/Work/program/gmp/lib /program/gmp/lib/libgmp.la'

# Libraries that this one depends upon.
dependency_libs=' -L/home/spy/Work/program/gmp/lib /home/spy/Work/program/gmp/lib/libgmp.la'

也就是把目錄改成完整的,這個過程的原因見mpc。

make時會看到其他警告,libgmp.la文件被moved,答案也是見mpc。

mpc

1
/usr/local
-> gmp,mpfr
<- gcc

$ cd /home/spy/Work/sources/mpc/build
$ ../mpc-1.0.2/configure --prefix=/program/mpc --oldincludedir=/program/mpc/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi --with-gmp=/home/spy/Work/program/gmp --with-mpfr=/home/spy/Work/program/mpfr
$ make
$ make install DESTDIR=/home/spy/Work

修改.la文件,

# Libraries that this one depends upon.
dependency_libs=' -L/home/spy/Work/program/gmp/lib -L/home/spy/Work/program/mpfr/lib /program/mpfr/lib/libmpfr.la /program/gmp/lib/libgmp.la -lm'

# Libraries that this one depends upon.
dependency_libs=' -L/home/spy/Work/program/gmp/lib -L/home/spy/Work/program/mpfr/lib /home/spy/Work/program/mpfr/lib/libmpfr.la /home/spy/Work/program/gmp/lib/libgmp.la -lm'

找不到*.la的問題

/usr/bin/sed: can't read /program/gmp/lib/libgmp.la: No such file or directory
libtool: link: `/program/gmp/lib/libgmp.la' is not a valid libtool archive

如果沒有我mpfr中的修改,編譯時就會出現(xiàn)這個錯誤。
編譯mpc的時候,應該讀取了mpfr中的libmpfr.la。然后根據dependency_libs中的路徑找libgmp.la,結果找不到。
dependency_libs的前一部分,應該是由我配置時指定的--with-gmp來確定,而后半部分,看看安裝后的gmp,也有個.la文件,文件中有個libdir,

# Directory that this library needs to be installed in:
libdir='/program/gmp/lib'

很明顯,這個libdir是根據編譯gmp時指定的prefix確定的。

如果把libdir手動改成/home/spy/Work/program/gmp/lib
再編譯mpfr,libmpfr.la中的dependency_libs就是,

# Libraries that this one depends upon.
dependency_libs=' -L/home/spy/Work/program/gmp/lib /home/spy/Work/program/gmp/lib/libgmp.la'

這樣也不會出現(xiàn)lib*.la文件被moved的警告。
由此可見,后半部分是由所依賴的.la文件中l(wèi)ibdir確定的。
我最后沒有選擇修改libdir,雖然修改libdir也可以編譯成功,而且沒有警告。

isl

3
/usr/local
-> gmp
<- gcc

$ cd /home/spy/Work/sources/isl/build
$ ../isl-0.12.2/configure --prefix=/program/isl --oldincludedir=/program/isl/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi --with-gmp-prefix=/home/spy/Work/program/gmp --with-gmp-exec-prefix=/home/spy/Work/program/gmp
$ make
$ make install DESTDIR=/home/spy/Work
# Libraries that this one depends upon.
dependency_libs=' -L/home/spy/Work/program/gmp/lib /program/gmp/lib/libgmp.la'
# Libraries that this one depends upon.
dependency_libs=' -L/home/spy/Work/program/gmp/lib /home/spy/Work/program/gmp/lib/libgmp.la'

如果只指定with-gmp-prefix,沒有 "--with-gmp-exec-prefix",竟然會有下面的錯誤。

/home/spy/Work/program/gmp/lib/libgmp.so: error adding symbols: File in wrong format

cloog

1
/usr/local
-> isl,gmp
<- gcc

$ cd /home/spy/Work/sources/cloog/build
$ ../cloog-0.18.1/configure --prefix=/program/cloog --oldincludedir=/program/cloog/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi --with-gmp-prefix=/home/spy/Work/program/gmp --with-gmp-exec-prefix=/home/spy/Work/program/gmp --with-isl=system --with-isl-prefix=/home/spy/Work/program/isl --with-isl-exec-prefix=/home/spy/Work/program/isl

修改Makefile libcloog-isl.la:

libcloog_isl_la_LDFLAGS = -version-info 4:0:0 \
  -L/home/spy/Work/program/isl/lib 

am_libcloog_isl_la_rpath = -rpath /home/spy/Work/program/isl/lib
$ make
$ make install DESTDIR=/home/spy/Work
# Libraries that this one depends upon.
dependency_libs=' -L/home/spy/Work/program/isl/lib -L/home/spy/Work/program/gmp/lib /program/isl/lib/libisl.la /program/gmp/lib/libgmp.la'
# Libraries that this one depends upon.
dependency_libs=' -L/home/spy/Work/program/isl/lib -L/home/spy/Work/program/gmp/lib /home/spy/Work/program/isl/lib/libisl.la /home/spy/Work/program/gmp/lib/libgmp.la'

--with-isl=system 目的是使用之前編譯的isl,cloog源碼中有也有份isl。


編譯時錯誤undefined reference

warning: libisl.so.10, needed by ./.libs/libcloog-isl.so, not found (try using -rpath or -rpath-link)

rpath的問題,解決見make前操作。

一看和isl有關,cloog的源碼中自帶了一份isl,我配置時沒用cloog中的,
當出現(xiàn)這個錯誤時,我配置成用cloog中的,這樣編譯cloog的時候,會有編譯isl的過程,結果編譯isl的時候就有錯誤。
看了一下cloog中的isl,版本低一些。
我單獨編譯這個isl或者在isl官網下載同樣的版本,都是出錯,為了解決cloog的錯誤,我決定先解決簡單一些的isl的錯誤入手。

isl-0.12.1版本的問題

isl_polyhedron_sample
isl_polytope_scan
isl_polyhedron_detect_equalities
isl_cat
isl_closure

以上就是編譯時出現(xiàn)過的有問題的make對象。在makefile文件中,用了下面的rpath即可解決。
-rpath /home/spy/Work/program/gmp/lib
rpath是運行時搜索程序庫的路徑,是gcc的參數,可以寫到編譯后的程序中的。

也許還有別的對象,但都用LINK

LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
  $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
  $(AM_LDFLAGS) $(LDFLAGS) -o $@

更改 AM_LDFLAGS = -rpath /home/spy/Work/program/gmp/lib
就都解決了。

但我發(fā)現(xiàn)了另一個方式,把這一個改對就可以

libisl.la: $(libisl_la_OBJECTS) $(libisl_la_DEPENDENCIES) $(EXTRA_libisl_la_DEPENDENCIES) 
  $(AM_V_CCLD)$(libisl_la_LINK) -rpath /home/spy/Work/program/gmp/lib $(libisl_la_OBJECTS) $(libisl_la_LIBADD) $(LIBS)

我不知道這樣做是否會出現(xiàn)什么問題,但還沒遇到,除了下面沒造成什么影響的。

按這個方式修改cloog的makefile的時候,
.la文件中,安裝路徑里出現(xiàn)的應該是cloog啊,竟然是isl,我做了修改,

# Directory that this library needs to be installed in:
libdir='/home/spy/Work/program/isl/lib'

改成

# Directory that this library needs to be installed in:
libdir='/program/cloog/lib'

其實這次編譯的時候isl已經是0.13版本了,這一版本拋棄了isl_int,
而cloog的發(fā)行版還沒有跟上,雖然git中有更新,但我不會用。這會有下面的問題。
unknown type name 'isl_int'

gcc

54
/usr/local
-> gmp,mpfr,mpc,isl,cloog
<- bash

$ cd /home/spy/Work/sources/gcc/build
$ ../gcc-4.9.0/configure --prefix=/program/gcc --oldincludedir=/program/gcc/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi --target=arm-none-linux-gnueabi --enable-shared --enable-threads --enable-languages=c --with-gmp=/home/spy/Work/program/gmp --with-mpfr=/home/spy/Work/program/mpfr --with-mpc=/home/spy/Work/program/mpc --with-isl=/home/spy/Work/program/isl --with-cloog=/home/spy/Work/program/cloog
$ make
$ make install DESTDIR=/home/spy/Work

gcc就是編譯器了,我們編譯軟件就靠它了,gcc也包含一些庫,我們的bash要用到。
gcc的配置選項太多了,我只額外用了
--enable-shared --enable-threads --enable-languages=c
也不知道是否需要。

bash

1
/usr/local
-> glibc,gcc,
<-

$ cd /home/spy/Work/sources/bash/build
$ ../bash-4.3/configure --prefix=/program/bash --oldincludedir=/program/bash/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi --without-bash-malloc
$ make
$ make install DESTDIR=/home/spy/Work

--with-installed-readline
本想加這個選項,但我編譯readline的時候,提示不讓交叉編譯,我做點修改還是編譯了。
但配置bash時,檢測到交叉編譯,竟然忽略了這一選項,那我還是別用這選項了。

我的bash好像有點問題,開發(fā)板中編譯軟件時,執(zhí)行makefile中的腳本發(fā)現(xiàn)的問題,在開發(fā)板中重新編譯了一次bash,問題消失了。
而且之前輸入命令滿一行不能自動換行,始終在一行。

在這里推薦個工具,readelf,這是binutils中的一個命令。可查看二進制文件的信息,我用它主要是為了看到所依賴的庫。

$ readelf -hld bin/bash

-a選項是打印所有的信息,我們用-hld就可以了。
看看我們編譯后的bash,它需要gcc中的libgcc_s.so.1,而我電腦中的bash卻不需要那個庫。


有了shell,我們就可以在開發(fā)板中驗證我們編譯的結果了。
至此,我們編譯了glibc,gmp,mpfr,mpc,isl,cloog,gcc,bash。
在復制到SD卡之前,我想應該先把mpfr,mpc,isl,cloog中的改動改回來。
根據prefix,將編譯后的程序復制到SD卡,/data/index/lib//data/index/bin/中添加相應的軟鏈接。
我并不是在這個時候才制作的軟鏈接,每編譯過一個程序,發(fā)現(xiàn)有bin和lib文件夾,就把軟鏈接做好了,直接復制到SD卡中就可以了。
至于怎么制作,我不擅長,寫個腳本應該比較好,但我沒學。
/data/configuration/中不必有配置文件。

在uEnv.txt中,把bootargs的init改為/program/bash

如果就這樣啟動的話,會提示找不到libgcc_s.so.1,因為這個庫不在ld.so的搜索路徑中。
目前的搜索路徑是/program/glibc/lib
所以/program/glibc/lib中有個libgcc_s.so.1就可以了,
可以放一個軟鏈接,就像/data/index/lib中的。
不要擔心,這只是臨時的。

接下來我們要在開發(fā)板中運行l(wèi)dconfig,這是glibc的一部分,
它會讀取ld.so.conf文件中的路徑,然后建立一個ld.so.cache文件,
這樣ld.so就能利用ld.so.cache找到那些路徑中的庫了。

ld.so.conf文件不存在,而我們構建的系統(tǒng)還沒有文本編輯器,所以要在啟動之前建立該文件。內容就是

/data/index/lib

很多文本文件都以空行結尾,我們也這么做吧。
那么這個文件要放到哪里呢,一般是/etc/中,但在我們構建的系統(tǒng)中,
ldconfig是到/program/glibc/etc/中找,所以要放到這個目錄中。

好,可以啟動開發(fā)板了,進到shell之后,運行l(wèi)dconfig。
/program/glibc/lib中的libgcc_s.so.1刪掉,重啟,看看是不是可以正常運行了?

這樣的方法并不好,應該讓編譯glibc的時候可以指定ld.so的搜索路徑。
其實我當初用了更不好的方法,我在內核參數中指定了LD_LIBRARY_PATH
我還試過把init改成ldconfig,但沒成功。由于ID為1的程序結束導致“kernel panic”倒是可理解。

雖然我們沒安什么程序,但bash是有內置命令的,比如切換目錄的cd,查看當前目錄的pwd

coreutils

2
/usr/local
->
<-

$ cd /home/spy/Work/sources/coreutils/build

也許要先編譯一遍本地版的,先看下面的解釋。

$ ../coreutils-8.22/configure --prefix=/program/coreutils --oldincludedir=/program/coreutils/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi --enable-install-program=arch,hostname

修改Makefile,.x.1對象,$(abs_top_builddir) 改 /home/spy/Work/sources/coreutils

$ make
$ make install DESTDIR=/home/spy/Work

--enable-install-program=arch,hostname
默認不安那2個,這樣就安了。

help2man不能得到help信息

help2man: can't get `--help' info from man/chroot.td/chroot
Try `--no-discard-stderr' if option outputs to stderr

help2man通過目標程序--help選項的輸出來生成man,
而我是交叉編譯,目標程序不能在我的系統(tǒng)中運行。
所以我先編譯了一遍本地版的,
把運行make那個目錄中的src文件夾復制到了/home/spy/Work/sources/coreutils
重新配置成交叉編譯,在make之前修改makefile文件,
將help2man的目標程序指定到本地版的。

linux-pam

1
/usr
->
<- util-linux,libcap,

$ cd /home/spy/Work/sources/linux-pam/build

先看下面的問題。

$ ../Linux-PAM-1.1.8/configure --prefix=/program/linux-pam --oldincludedir=/program/linux-pam/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work

pam與認證有關,如果沒有這個,編譯util-linux的時候就不會有l(wèi)ogin。
util-linux的配置中并沒有指定pam的選項,所以安裝后,我把pam的庫和頭文件做了軟連接,放到我交叉編譯器搜索庫的目錄中了。
我也嘗試過把gcc依賴的庫放到交叉編譯器搜索庫的目錄中,但遇到了新的問題,時間關系,沒有研究。

pam的庫中也有個la文件,根據pam所放的目錄,做類似下面的修改。
libpam_misc.la

# Libraries that this one depends upon.
dependency_libs=' /home/spy/Work/program/linux-pam/lib/libpam.la -ldl'

include/security/
需要pam頭文件的程序在那個目錄找而不是include/
編譯其他程序的時候如果提示找不到頭文件,可改下目錄。

yywrap的問題

搜索后這個函數在flex中,安裝后,我也不太會用,

conf/pam_conv1/Makefile  
LIBS = -lfl

doc/specs/Makefile

還有一些其他新問題,于是換策略。

conf/pam_conv1/pam_conv_l.c

int     yywrap (void)
{
  return 1;
}

doc/specs/parse_l.c

int     yywrap (void)
{
  return 1;
}

就是在那2個c源文件中添加yywrap函數,
反正felx中有個libyywrap.c,里面的函數就這個樣子。

ncurses

3
/usr/local
->
<- util-linux,nano,vim

$ cd /home/spy/Work/sources/ncurses/build
$ ../ncurses-5.9/configure --prefix=/program/ncurses --oldincludedir=/program/ncurses/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi --target=arm-none-linux-gnueabi --with-shared --enable-widec --with-build-cc=gcc
$ make
$ make install DESTDIR=/home/spy/Work

也是放到交叉編譯器搜索庫的目錄中,再做個下面那樣的軟連接,因為有些程序找的是ncurses。
ncurses -> ncursesw

util-linux

3
/usr
-> pam,ncurses
<-

$ cd /home/spy/Work/sources/util-linux/build

先看下面的問題。

$ ../util-linux-2.24.2/configure --prefix=/program/util-linux --oldincludedir=/program/util-linux/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ su
# make install DESTDIR=/home/spy/Work
  • 帶ncurses編譯時,
    text-utils/more.c:200:51
    text-utils/pg.c:60:18
    text-utils/ul.c:46:41
    term-utils/setterm.c:113:18
    misc-utils/cal.c:82:19
    提示找不到term.h,把源文件中改成下面那樣就好了。
    <ncurses/term.h>

  • 帶pam庫編譯時
    cannot find the library /program/linux-pam/lib/libpam.la' or unhandled argument/program/linux-pam/lib/libpam.la'
    修改libpam_misc.la中的路徑,見pam中的修改。

安裝時,不能改變bin/wall的用戶組為tty
我采用了安裝時切換用戶為root的方法。

libcap

0
-> pam
<- systemd,

$ cd /home/spy/Work/sources/libcap/libcap-2.24

將makefile要引入的文件Make.Rules做如下修改。

CC := arm-none-linux-gnueabi-gcc
BUILD_CC := gcc
AR := arm-none-linux-gnueabi-ar
RANLIB := arm-none-linux-gnueabi-ranlib
SYSTEM_HEADERS = /home/spy/Software/arm-2013.11/arm-none-linux-gnueabi/libc/usr/include
LIBATTR := no
$ make prefix=/program/libcap lib=lib DESTDIR=/home/spy/Work
$ make install prefix=/program/libcap lib=lib DESTDIR=/home/spy/Work

完成以上步驟,也是做一份軟連接和交叉編譯器的庫放到一起。

xz

1
/usr/local
->
<- systemd

$ cd /home/spy/Work/sources/xz/build
$ ../xz-5.0.5/configure --prefix=/program/xz --oldincludedir=/program/xz/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work

kmod

1
/usr
->
<- systemd

$ cd /home/spy/Work/sources/kmod/build
$ ../kmod-17/configure --prefix=/program/kmod --oldincludedir=/program/kmod/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work

編譯完的目錄中是有一些軟鏈接指向kmod命令的,但安裝完的目錄里沒有那些軟鏈接。
這些軟鏈接很有意思啊,比如insmod指向kmod,輸入insmod實際運行的不是kmod,而是kmod insmod。大概是這樣的。

kmod與模塊有關,所以你的系統(tǒng)中應該放上編譯內核時的模塊了。

systemd

22
/usr
-> libcap
<-

$ cd /home/spy/Work/sources/systemd/build

修改configure,避免rpl_malloc的錯誤

  if test "$cross_compiling" = yes; then :
  ac_cv_func_malloc_0_nonnull=no 改成 yes

配置出錯時提示過的:
sys/capability.h 在libcap中
pkg-config
intltool
gperf

后3個不是庫,編譯時被調用,又不像編譯器那樣為另一個平臺生成程序,
所以應該不必為我構建的系統(tǒng)編譯他們,用自己Linux系統(tǒng)的包管理器安上就好了。

$ ../systemd-212/configure --prefix=/program/systemd --oldincludedir=/program/systemd/oldinclude --with-rootprefix=/program/systemd/root --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi --disable-seccomp --disable-blkid --disable-libcryptsetup --disable-audit --disable-acl --disable-xattr --disable-selinux --disable-gcrypt --disable-qrencode --disable-microhttpd --disable-gudev --without-python

看下面修改Makefile。

$ make
$ make install DESTDIR=/home/spy/Work

--with-rootprefix=/program/systemd/root
由于安裝的時候會有一些東西安裝在了program文件夾之外,指定這個選項為安裝路徑內部就可以了,
root是我隨便起的,但最好與其他文件夾獨立。

后面那些都是可選的軟件包,我全禁用了。
還有一些可選的如kmod,xz,沒有禁用。
曾經禁用過kmod,發(fā)現(xiàn)不能自動載入模塊。

編譯時和kmod有關的錯誤。

KMOD_CFLAGS = -I/home/spy/Work/program/kmod/include
KMOD_LIBS = -L/home/spy/Work/program/kmod/lib -lkmod
這是Makefile中的參數,有些對象需要但并沒加上。
于是我修改了Makefile。

test_CFLAGS = \
  $(KMOD_CFLAGS)

.c.o:
$(test_CFLAGS)

Makefile前部分加了test_CFLAGS,然后在.c.o對象的適當位置加上$(test_CFLAGS)

test_rtnl_manual_LDADD = \
  libsystemd-internal.la \
  libsystemd-shared.la \
  -L/home/spy/Work/program/kmod/lib -lkmod

這里加上了庫的目錄。

關于systemd

終于到了真正的init程序,這么偉大的程序,竟然沒找到學習的文檔。

systemd包含了udev。

/etc/mtab -> /proc/self/mounts
所以/data/configuration/中應該放個mtab了。
如果不放,啟動的時候會有警告提示。


systemd對一些目錄的要求。
參見http://www.freedesktop.org/wiki/Software/systemd/FileHierarchy/

  • /, /usr, /etc must be mounted when the host systemd is first invoked. This may
    be achieved either by using the kernel's built-in root disk mounting (
    in which case /, /usr and /etc need to be on the same file system), or
    via an initrd, which could mount the three directories from different sources.

  • /bin, /sbin, /lib (and /lib64 if applicable) should reside on /, or be symlinks
    to the /usr file system (recommended). All of them must be available
    before the host systemd is first executed.

  • /var does not have to be mounted when the host systemd is first invoked,
    however, it must be configured so that it is mounted writable
    before local-fs.target is reached (for example, by simply listing it in /etc/fstab).

  • /tmp is recommended to be a tmpfs (default), but doesn't have to. If configured,
    it must be mounted before local-fs.target is reached (for example, by listing it in /etc/fstab).

  • /dev must exist as an empty mount point and will automatically be mounted
    by systemd with a devtmpfs. Non-devtmpfs boots are not supported.

  • /proc and /sys must exist as empty mount points and
    will automatically be mounted by systemd with procfs and sysfs.

  • /run must exist as an empty mount point and will automatically be mounted by systemd with a tmpfs.

測試

又到了體驗成就感的時候,目前,我們已經擁有的程序,
glibc,gmp,mpfr,mpc,isl,cloog,gcc,bash,
coreutils,linux-pam,ncurses,util-linux,libcap,xz,kmod,systemd。
放到SD卡中。
也許最好把SD卡中文件的用戶和組改成root,但是util-linux中的wall屬于tty組。
我下面這2條命令是不全的。

# chown -R 0:0
# chgrp -v tty /program/util-linux/bin/wall

由于有了新的程序庫,而且是systemd需要用到的,所以先別急著改把init改成systemd,
那樣應該會提示找不到庫的,所以先用bash,執(zhí)行一下ldconfig,然后再改,
init=/program/systemd/root/lib/systemd/systemd


/data/configuration/中的文件,目前就有個mtab,
如果沒有passwd文件,會有登陸的提示,還會讓輸入密碼,然后就是登陸失敗,所以要創(chuàng)建。
/data/configuration/passwd

root::0:0:root:/user/root:/program/bash/bin/bash

目前不能設置密碼,設置了會登陸失敗,不知為什么,可能為了安全吧。所以密碼部分空著。


/data/configuration/pam.conf

other auth    required  pam_unix.so nullok
other account   required  pam_unix.so
other session   required  pam_unix.so
other password  required  pam_unix.so

這是pam的配置文件,可看看pam的手冊,內容沒深入研究,是我自己看了很多配置后定的。

第一部分是需要pam的程序的名字,如login,改成login也可以。
最后的nullok選項是必要的,這允許沒有密碼的登陸。

前面說到,不能在passwd中設置密碼,我本以為加了broken_shadow選項就可以了,但不是。

pam也可以在/etc/pam.d/中找配置文件,這個是shadow的一部分,里面不止一個配置文件。
如果pam.d存在,則忽略pam.conf。


現(xiàn)在啟動BeagleBone Black吧,
systemd啟動后,會在/data/configuration/中創(chuàng)建一個machine-id文件,
最后systemd會啟動在ttyO0上的登陸服務,提示登陸,輸入root,確定后就看見bash了。

一些命令,
顯示這次登陸的日志,

# journalctl -b

重啟,

$ systemctl reboot

關機

$ systemctl poweroff

但我的關上后,電源指示燈還亮著,別的燈倒是滅了。

shadow

1
/usr/local
->
<-

$ cd /home/spy/Work/sources/shadow/build

看下面修改configure。

$ ../shadow-4.2.1/configure --prefix=/program/shadow --oldincludedir=/program/shadow/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi --enable-shared
$ make
$ make install DESTDIR=/home/spy/Work

vflg,Vflg,is_sub_uid,wflg,Wflg 未定義

修改configure
搜索“run test”,在附近做修改。

if test "$cross_compiling" = ye;

不是“yes”就好。

  id32bit="yes"

else中的也改成“yes”。

一切是為了實現(xiàn)

ENABLE_SUBIDS_FALSE='#'
ENABLE_SUBIDS_TRUE=''

shadow中有與已安裝程序相同的命令,我選擇了shadow中的。
util-linux {login,nologin,su}
coreutils {groups}

它的配置文件要復制一份到/etc/中。
它的配置文件不可以直接用,看看pam.d中的login文件。
內容的格式也就是少了第一部分,這部分用文件名表示了。
奇怪的是你會在配置中發(fā)現(xiàn)include,但后面的文件沒有。
你也會看到額外的配置,先參照pam.conf改吧。

登陸的時候,會提示一些,

configuration error - unknown item

這與shadow中的login.defs有關。

binutils

4
/usr/local
->
<-

$ cd /home/spy/Work/sources/binutils/build
$ ../binutils-2.24/configure --prefix=/program/binutils --oldincludedir=/program/binutils/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi --target=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work

這里面有匯編器,連接器等,我的目的是可以在開發(fā)板中構建程序。
LFS的網站上說,這個要在glibc和gcc之前編譯,但我是現(xiàn)在編譯的,

make

1
/usr/local
->
<-

$ cd /home/spy/Work/sources/make/build
$ ../make-4.0/configure --prefix=/program/make --oldincludedir=/program/make/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work

sed

0
/usr/local
->
<-

$ cd /home/spy/Work/sources/sed/build
$ ../sed-4.2.2/configure --prefix=/program/sed --oldincludedir=/program/sed/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work

configure腳本中會用到的,還有grep,gawk。

grep

0
/usr/local
->
<-

$ cd /home/spy/Work/sources/grep/build
$ ../grep-2.9/configure --prefix=/program/grep --oldincludedir=/program/grep/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work

gawk

1
/usr/local
->
<-

$ cd /home/spy/Work/sources/gawk/build
$ ../gawk-4.1.1/configure --prefix=/program/gawk --oldincludedir=/program/gawk/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work

nano

0
/usr/local
-> ncurses
<-

$ cd /home/spy/Work/sources/nano/build

好像要修改源文件。或者修改configure的CPPFLAGS?我選擇了前者。

$ ../nano-2.2.6/configure --prefix=/program/nano --oldincludedir=/program/nano/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work
src/nano.h:92:20: fatal error: curses.h: No such file or directory
#elif defined(HAVE_NCURSES_H)
#include <ncursesw/ncurses.h>
#else
/* Curses support. */
#include <ncursesw/curses.h>
#endif /* CURSES_H */

less

0
/usr/local
->
<-

$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/less/build

$ ../less-458/configure --prefix=/program/less --oldincludedir=/program/less/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work

有了它,journalctl的輸出就舒服了。man的輸出也是放到less中。

findutils

/usr/local
->
<-
安裝程序的時候,有時會需要這個,比如vim。
在開發(fā)板中編譯的。有個時間的問題,

checking whether build environment is sane... configure: error: newly created file is older than distributed files!
Check your system clock

看過其他為開發(fā)板提供的系統(tǒng),啟動信息中有一條設置了時間,而我的不能。
設置一下時間就好了。

date -s 20140402

diffutils

1
/usr/local
->
<-

$ cd /home/spy/Work/sources/diffutils/build
$ ../diffutils-3.3/configure --prefix=/program/diffutils --oldincludedir=/program/diffutils/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work

tar

/usr/local
->
<-

$ cd /home/spy/Work/sources/tar/build
$ ../tar-1.27.1/configure --prefix=/program/tar --oldincludedir=/program/tar/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work

gzip

0
/usr/local
->
<-

$ cd /home/spy/Work/sources/gzip/build
$ ../gzip-1.6/configure --prefix=/program/gzip --oldincludedir=/program/gzip/oldinclude --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work

好了,現(xiàn)在我的系統(tǒng)已經可以編譯軟件了。
雖然還缺少一些常用的軟件。但構建Linux的思想已基本掌握,
再這樣安軟件安下去沒什么意義了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,460評論 6 538
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,067評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,467評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,468評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,184評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,582評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,616評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,794評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 49,343評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,096評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,291評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,863評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,513評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,941評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,190評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,026評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,253評論 2 375

推薦閱讀更多精彩內容