以下很多都是回忆,不一定准了。
注意这里的文章自动换行了。
我构建的目标平台为BeagleBone Black,
'http://beagleboard.org/'。
交叉编译工具为Sourcery CodeBench Lite,
'http://www.mentor.com/'。
要构建Linux,很简单,只有3个部分,
1,bootloader,即启动引导程序,我选择U-Boot。
2,Linux内核。
3,应用程序。
我还没研究是什么决定了32位和64位。
我主要的资料,
Running Linux
介绍Linux的书,这才叫入门级,了解下Linux的思想即可,书的内容可能有些过时,
这本书不是介绍怎么使用Linux的。如果想知道怎么使用Linux,
可看看Linux Pocket Guide,很薄。
鸟哥的书也不错,感觉挺详细的,好于大部分书,我没看。
我连shell脚本都不会写呢,很多命令没用过,这与构建Linux关系不大。
Building Embedded Linux Systems
教构建嵌入式Linux的,了解下思想即可。
http://www.linuxfromscratch.org/
教构建各种Linux的网站,最关键的是网站给出了Linux由哪些应用程序构成。
我没有用网站中的方式,sed那种命令不会。也是了解下思想即可。
If you can’t explain it simply, you don’t understand it well enough.
--Albert Einstein
BeagleBone Black有4种启动方式,我选择用SD卡。
准备SD卡,将SD卡插到电脑中,在我的系统中被识别为/dev/sdb。
分区:
# fdisk /dev/sdb
用法很简单,输入'm',就可得到帮助。
第一个分区64M,类型为FAT32 (LBA),加上启动标记。
第二个分区为余下的全部,类型默认为Linux,不必改。
参考过程是这样的,
输入'o',新建一个空DOS分区表,这会清除所有分区。
输入'p',会列出分区列表,此时应该没有。
输入'n'来添加新分区,直接'enter',接受默认为主分区,'enter'接受默认为第一分区,
'enter'接受默认的开始扇区,输入'+64M',设置分区大小为64M。
输入't',来改变分区类型,自动选择了第一个分区,输入l可列出所有分区列表的代码,
输入'c'选择W95 FAT32(LBA)。
输入'a',在第一分区设置可启动标记。
输入'n','enter'主分区,'enter'第二个,'enter'起始扇区,'enter'结束扇区。
输入'w',将改动写入分区表。
格式化:
# mkfs.vfat -F 32 /dev/sdb1
# mkfs.ext4 /dev/sdb2
第一个分区用来放U-Boot,板子启动后就会找一个叫MLO的文件,编译U-Boot后,就会生成
一个MLO,不必担心。
第二个分区用来放Linux系统。
sdb2被格式化后,里面自动有个lost+found,文件系统的结构中正好有一条:
/lost+found: Filesystem-specific recoverable data
===============================================================================
我的文件系统目录结构
/
/bin --> /usr/bin/
/boot/
/dev/
/etc/
/home/
/home/root
/lib --> /usr/lib/
/mnt/
/proc/
/run/
/sbin --> /usr/bin/
/sys/
/tmp
/usr/
/usr/app/
/usr/bin/
/usr/include/
/usr/lib/
/usr/sbin --> bin/
/usr/share/
/usr/share/man/
/var/
/var/run --> /run/
===============================================================================
编译时的一些配置等,我为了方便调用,放到这里,不要看。
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ export PATH=$PATH:/home/spy/Work/U-Boot/u-boot/tools
$ export CROSS_COMPILE=arm-none-linux-gnueabi-
# chown -R 0:0
# chgrp -v tty /usr/app/util-linux/bin/wall
# chown -R spy:users
找readelf结果中带"Shared library"的行
readelf -ld | grep "Shared library"
以可读写重新挂载根文件系统
mount -n -o remount,rw /
放到交叉编译器搜索库中的程序库
libcap,pam,ncurses,gdbm,db,iptables
coreutils与util-linux重复的命令。
kill
shadow与util-linux重复的命令。
{login,nologin,su}
shadow与coreutils重复的命令。
groups
===============================================================================
============ http://www.denx.de/wiki/U-Boot/WebHome
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ export CROSS_COMPILE=arm-none-linux-gnueabi-
$ make O=../u-boot distclean
$ make O=../u-boot am335x_boneblack_config
$ make O=../u-boot all
--------------------------------------------------------------------------------
源码中正好有am335x_boneblack这个配置文件,对应我的开发板,想知道可用的配置文件
看README吧,它会告诉你到另一个文件中找。
忘了是编译U-Boot还是Linux内核的时候,提示我的系统中缺少bc,用你的包管理器安上就好了。
/*------------------------------------------------------------------------------
摘自TI的wiki,让你了解MLO和u-boot.img是什么。
大概是AM335X芯片中的程序较小,只为了4种启动方式初始化,
然后找到MLO,运行MLO进一步初始化,如DDR3内存。
MLO最后找到u-boot.img,运行之。u-boot.img这个名字应该是在MLO的代码中指定的。
提示:TI的StarterWare中的2个文件叫MLO和app。
Two stage U-Boot design
This section gives an overview of the two stage U-Boot approach adopted for AM335X.
The size of the internal RAM in AM335X is 128KB out of which
18KB at the end is used by the ROM code. Also,
1 KB at the start (0x402f0000 - 0x402f0400) is secure and it cannot be accessed
This places a limit of 109KB on the size of the U-Boot binary which
the ROM code can transfer to the internal RAM and use as an initial stack
before initialization of DRAM.
Since it is not possible to squeeze in all the functionality
that is normally expected from U-Boot in < 110KB (after setting aside some space
for stack, heap etc) a two stage approach has been adopted.
Initial stage initalize only the required boot devices (NAND, MMC, I2C etc);
2nd full stage initall all other devices (ethernet, timers, clocks etc).
The 1st binary is generated MLO and the 2nd stage is generated as u-boot.img.
------------------------------------------------------------------------------*/
编译完后,现在就可以找找成就感了,
将MLO和u-boot.img复制到SD卡的第一个分区里;
将串口调试用的线与计算机相连,启动串口调试程序,如Putty。
将SD卡插入开发板,保持按下板子上的启动选择键,插上电源,板子会从SD卡启动,
可以松开启动选择键了。
Putty的窗口上会打印一些信息,你会看到一个1秒的倒计时,然后U-Boot会运行环境变量中
已经设置好的一些列命令,比如将Linux内核载入内存,但此时还没有内核文件,U-Boot会
停留在它自己的命令行中,你可以输入命令,如reset,这会让板子重启,倒计时的时候
按下计算机上的任意键,U-Boot就不会运行环境变量中的命令了,可玩一玩下面的演示。
给出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
============ http://www.kernel.org/
内核配置文件我在'https://github.com/beagleboard/kernel/tree/3.13/configs'找的,
复制一份名字改'.config'放到O指定的目录中。
这样就可以用'make oldconfig'了。
我的内核版本是Linux-3.13.5,并没有提示新的配置。
如果要修改的话,要注意systemd对内核的配置是有要求的,我并没有改。
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ export PATH=$PATH:/home/spy/Work/U-Boot/u-boot/tools
$ export CROSS_COMPILE=arm-none-linux-gnueabi-
$ make O=../linux ARCH=arm help
$ make O=../linux ARCH=arm mrproper
$ make O=../linux ARCH=arm oldconfig
$ make O=../linux ARCH=arm LOADADDR=0x80008000 uImage
$ make O=../linux ARCH=arm LOADADDR=0x80008000 dtbs
$ make O=../linux ARCH=arm LOADADDR=0x80008000 modules
$ make O=../linux ARCH=arm LOADADDR=0x80008000 INSTALL_MOD_PATH=/home/spy/Work/root modules_install
$ make O=../linux ARCH=arm LOADADDR=0x80008000 INSTALL_FW_PATH=/home/spy/Work/fw firmware_install
$ make O=../linux ARCH=arm LOADADDR=0x80008000 INSTALL_HDR_PATH=/home/spy/Work/root/hdr headers_install
--------------------------------------------------------------------------------
'make help'是否指定ARCH,输出内容是不同的。
uImage就是压缩后的Linux内核,编译时需要mkimage这个工具,编译U-Boot的时候会生成那个工具,
所以我编译内核之前指定了该工具的目录。
-dts --> device tree source
-dtb --> device tree blob
-dtbo --> device tree blob overlay
-dtc --> device tree compile
没研究为什么编译设备树是dtbs,是在make help的帮助中看到的。
内核的配置中指定了很多把驱动编译成模块的,这部分需要'make modules'来单独编译。
我构建完的系统并没有用到这些modules,插个U盘是可用的。
编译完成后,可在输出文件夹的'arch/arm/boot'找到zImage, uImage和dts子文件夹,
dts里面有am335x-boneblack.dtb。zImage也是内核,也可以用,但我用的uImage。
最后那三个安装目录自己选个更好的吧。
modules会安在'lib/modules'和'lib/firmware'2个文件夹中。
/*------------------------------------------------------------------------------
安装modules的时候,可能会提示depmod出问题,据说正常,那不是处理交叉编译的模块的。
但我还是看到了depmod后应该出现的modules.dep文件。
depmod是用来构建模块依存关系的,目的是,当用insmod装载某模块的时候,可能会失败,
因为这个模块依赖的其他模块还没有装入内核,depmod构建完依赖关系后,用另外一个命令
装载模块,即可自动装载模块所依赖的其他模块。
------------------------------------------------------------------------------*/
firmware也安在'lib/firmware'中,但与modules中的不同。我目前不知道firmware是干什么的。
headers还是需要安装的,它就像glibc那样,编译程序时被调用。
--------------------------------------------------------------------------------
下面可以验证了。
将uImage文件,dts文件夹复制到SD卡第二个分区的/boot/里。
其实dts中应该只需am335x-boneblack.dtb。
启动开发板前应该了解下U-Boot如何载入Linux。
/*------------------------------------------------------------------------------
U-Boot中最关键的环境变量
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开始。
------------------------------------------------------------------------------*/
提示:我的研究在后面。现在可不必研究直接看我的处理。
编译后的U-Boot是不能引导uImage的,通过printenv看U-Boot的环境变量,可看到
它找的是zImage,而且am335x-boneblack.dtb是在/boot/中找,不是/boot/dts/。
如果将zImage和am335x-boneblack.dtb放到/boot中应该能引导。
为了符合我的要求,要修改环境变量,可以用editenv修改环境变量后saveenv。
但还是别这么做了,我不知道它把环境变量保存到哪里去了。我以为把MLO和u-boot.img换回
原始的可以恢复默认的环境变量值,但不是这样,把SD卡格式化后也没用。
有可能是存到eMMC中了,我想尽各种办法破坏eMMC的数据,用了
'dd if=/dev/zero of=/dev/mmcblk1'也不行。
除了mmcblk1还有个mmcblk1boot,可能是存到那里了,记着那个设备比较奇怪,没有验证。
最后用'env default -a'然后'saveenv'恢复默认了。
另一个方法是创建一个uEnv.txt文件,将它和MLO放到一起,内容如下。
该文件中的环境变量会覆盖掉默认的环境变量。
/*
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=/usr/lib/systemd/systemd
*/
一共6行,最后一行空白。
改动不是很大,bootfile修改了内核名字,
loadfdt中只是在目录中加了“dts/”,
mmcloados主要是把bootz改成bootm。
mmcroot把只读改成了读写,原因是systemd启动后会创建一个machine-id到/etc中。
也许有其他办法,如/etc/fstab文件,但我为了简单没创建那个文件。
mmcargs只是在后面指定了init为systemd,也有其他方法,如init为指向systemd的软链接。
启动BeagleBone Black,待内核启动后会打印很多信息,最后你将目睹“kernel panic”,
这是因为我们目前并没有init程序,为了找到成就感,你可以编译下面
静态链接的“Hello world!”,放到某个目录中,然后在U-Boot的mmcargs变量中
把init指定为那个hello。
hello.c
/*-----------------------------
#include
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步是导入环境变量,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这个环境变量也没找到,在其他U-Boot中发现是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个程序。
迫不及待验证编译结果的话可以先把交叉编译器中的库复制到开发板系统中,
我当初就那么做的。
glibc是程序库了,几乎动态链接的程序都要用到了,"Hello world"中的printf函数都需要。
bash是个shell,提供了人与计算机交互的界面。
coreutils里有很多常用命令,如'ls'。
util-linux也是有很多命令,如mount,login,fdisk。
systemd是个init程序。
shadow是和登陆相关的,主要是把'/etc/passwd'文件里的密码变成“x”,
里面有login,passwd,useradd等命令。
其实系统系统后的第一个程序是systemd,但它的文档较少,不了解是怎么工作的,
所以先保证其他的能工作,再研究。
至于怎么编译,源码中会有README,INSTALL等文档。
需要注意的是我构建的系统与大多数Linux不同,我把所有程序都安装在了
/usr/app/{程序}/中。这是我改进Linux的开始,咱有大计划呀!
我的想法如下,
对于程序库,依旧在/usr/lib/中搜索,里面除了子文件夹都是软链接,指向app中
相应的程序库。
对于/usr/bin/中的程序,也是软链接。
对于/etc/中的配置文件,其实有些程序不在那个目录找配置文件了,如果还在那个目录找,
那么里面不是软链接,就是传统的配置文件。
============ [/usr/local] http://www.gnu.org/software/libc/
>
< bash, //这2个依赖和被依赖的,仅供参考,肯定不全的,下面也一样。
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/glibc/glibc-build
$ ../glibc-2.19/configure --prefix=/usr/app/glibc --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install install_root=/home/spy/Work/sources/glibc/glibc
--------------------------------------------------------------------------------
源码中并没有makefile文件,这需要运行configure来生成。
通过“configure --help”查看可用的选项。
prefix为安装目录;
build和host用来指定系统类型。可看看autoconf的手册中“Specifying target triplets”。
/*------------------------------------------------------------------------------
build - 构建程序的系统,在该系统中配置和编译程序。
host - 构建后的程序运行在此系统中。
target - 编译工具为此系统生成程序。
这个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系统中,让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”这个选项可用。
在我的系统中猜测出的值为“x86_64-unknown-linux-gnu”。
在BeagleBone Black中,结果为“armv7l-unknow-linux-gnueabihf”。这个结果应该是
不知道的,因为我是在BeagleBone Black已经可用的系统中运行的config.guess。
而我们的系统还没有构建出来呢,不可能运行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”已经到了,但我还是指定了。
------------------------------------------------------------------------------*/
我们编译程序是用在其他的系统中,如果不指定install_root,它就要往prefix指定的目录安了,
不要这样,我的路径还好,如果是/usr/lib/,那就破坏了你正使用的系统,不过我用的是普通用户,
应该没权限往那个目录安。
有了install_root,就会安装到/home/spy/Work/sources/glibc/glibc/usr/app/glibc,看看
makefile文件就会明白原理。
那么把prefix指定为那个完整的目录,不使用install_root行不行呢。最好别这样。
构建完glibc,其中的ld.so并不是在/lib/或/usr/lib/中找程序库,而是在glibc的库
被安装到的目录中找,即'/usr/app/glibc/lib'。
可见,这个prefix会记录到生成的程序中,所以最好别让目录那么长,那么乱。
问题又来了,ld.so竟然不在/usr/lib/中找程序库,这可是传说中的默认目录啊。
我的处理是在构建的系统中运行ldconfig,在bash中说。
============ [/usr/local] https://gmplib.org/
>
< mpfr,mpc,isl,cloog,gcc
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/gmp/gmp-build
$ ../gmp-5.1.3/configure --prefix=/usr/app/gmp --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work/sources/gmp/gmp
--------------------------------------------------------------------------------
这个和下面的4个都是为gcc服务的。
这里的安装目录用的是DESTDIR,看看源代码里的文档吧。
libtool: install: warning: remember to run `libtool --finish /usr/local/lib'
安装时遇到个警告,这个应该和ldconfig这个命令有关,应该是为了glibc的ld程序能找到这个库,我没执行这一步。
============ [/usr/local] http://www.mpfr.org/
> gmp,
< mpc,gcc
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/mpfr/mpfr-build
$ ../mpfr-3.1.2/configure --prefix=/usr/app/mpfr --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi --with-gmp=/home/spy/Work/sources/gmp/gmp/usr/app/gmp
$ make
$ make install DESTDIR=/home/spy/Work/sources/mpfr/mpfr
--------------------------------------------------------------------------------
修改lib/libmpfr.la,
# Libraries that this one depends upon.
dependency_libs=' -L/home/spy/Work/sources/gmp/gmp/usr/app/gmp/lib /usr/app/gmp/lib/libgmp.la'
到
# Libraries that this one depends upon.
dependency_libs=' -L/home/spy/Work/sources/gmp/gmp/usr/app/gmp/lib /home/spy/Work/sources/gmp/gmp/usr/app/gmp/lib/libgmp.la'
也就是把目录改成完整的,这个过程的原因见mpc。
--------------------------------------------------------------------------------
libtool: install: warning: remember to run `libtool --finish /usr/local/lib'
警告依旧,不管他,怕他影响我正使用系统中的库。
应该还会看到其他警告,如某个.la文件被moved,答案也是见mpc。
============ [/usr/local] http://www.multiprecision.org/
> gmp,mpfr
< gcc
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/mpc/mpc-build
$ ../mpc-1.0.2/configure --prefix=/usr/app/mpc --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi --with-gmp=/home/spy/Work/sources/gmp/gmp/usr/app/gmp --with-mpfr=/home/spy/Work/sources/mpfr/mpfr/usr/app/mpfr
$ make
$ make install DESTDIR=/home/spy/Work/sources/mpc/mpc
--------------------------------------------------------------------------------
修改.la文件,
# Libraries that this one depends upon.
dependency_libs=' -L/home/spy/Work/sources/gmp/gmp/usr/app/gmp/lib -L/home/spy/Work/sources/mpfr/mpfr/usr/app/mpfr/lib /usr/app/mpfr/lib/libmpfr.la /usr/app/gmp/lib/libgmp.la -lm'
到
# Libraries that this one depends upon.
dependency_libs=' -L/home/spy/Work/sources/gmp/gmp/usr/app/gmp/lib -L/home/spy/Work/sources/mpfr/mpfr/usr/app/mpfr/lib /home/spy/Work/sources/mpfr/mpfr/usr/app/mpfr/lib/libmpfr.la /home/spy/Work/sources/gmp/gmp/usr/app/gmp/lib/libgmp.la -lm'
--------------------------------------------------------------------------------
libtool: install: warning: remember to run `libtool --finish /usr/local/lib'
/*------------------------------------------------------------------------------
找不到*.la的问题
/usr/bin/sed: can't read /usr/app/gmp/lib/libgmp.la: No such file or directory
libtool: link: `/usr/app/gmp/lib/libgmp.la' is not a valid libtool archive
如果没有我mpfr中的修改,编译时就会出现这个错误。
编译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='/usr/app/gmp/lib'
很明显,这个libdir是根据编译gmp时指定的prefix确定的。
如果把libdir手动改成'/home/spy/Work/sources/gmp/gmp/usr/app/gmp/lib',
再编译mpfr,libmpfr.la中的dependency_libs就是,
# Libraries that this one depends upon.
dependency_libs=' -L/home/spy/Work/sources/gmp/gmp/usr/app/gmp/lib /home/spy/Work/sources/gmp/gmp/usr/app/gmp/lib/libgmp.la'
这样也不会出现lib*.la文件被moved的警告。
由此可见,后半部分是由所依赖的.la文件中libdir确定的。
我最后没有选择修改libdir,虽然修改libdir也可以编译成功,而且没有警告。
------------------------------------------------------------------------------*/
============ [/usr/local] http://freecode.com/projects/isl
> gmp
< gcc
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/isl/isl-build
$ ../isl-0.12.2/configure --prefix=/usr/app/isl --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi --with-gmp-prefix=/home/spy/Work/sources/gmp/gmp/usr/app/gmp --with-gmp-exec-prefix=/home/spy/Work/sources/gmp/gmp/usr/app/gmp
$ make
$ make install DESTDIR=/home/spy/Work/sources/isl/isl
--------------------------------------------------------------------------------
# Libraries that this one depends upon.
dependency_libs=' -L/home/spy/Work/sources/gmp/gmp/usr/app/gmp/lib /usr/app/gmp/lib/libgmp.la'
# Libraries that this one depends upon.
dependency_libs=' -L/home/spy/Work/sources/gmp/gmp/usr/app/gmp/lib /home/spy/Work/sources/gmp/gmp/usr/app/gmp/lib/libgmp.la'
--------------------------------------------------------------------------------
libtool: warning: remember to run 'libtool --finish /usr/local/lib'
============ [/usr/local] http://www.bastoul.net/cloog/index.php
> isl,gmp
< gcc
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/cloog/cloog-build
$ ../cloog-0.18.1/configure --prefix=/usr/app/cloog --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi --with-isl=system --with-isl-prefix=/home/spy/Work/sources/isl/isl/usr/app/isl --with-isl-exec-prefix=/home/spy/Work/sources/isl/isl/usr/app/isl --with-gmp-prefix=/home/spy/Work/sources/gmp/gmp/usr/app/gmp --with-gmp-exec-prefix=/home/spy/Work/sources/gmp/gmp/usr/app/gmp
修改Makefile libcloog-isl.la:
libcloog_isl_la_LDFLAGS = -version-info 4:0:0 \
-L/home/spy/Work/sources/isl/isl/usr/local/lib
am_libcloog_isl_la_rpath = -rpath /home/spy/Work/sources/isl/isl/usr/app/isl/lib
$ make
$ make install DESTDIR=/home/spy/Work/sources/cloog/cloog
--------------------------------------------------------------------------------
# Libraries that this one depends upon.
dependency_libs=' -L/home/spy/Work/sources/isl/isl/usr/app/isl/lib -L/home/spy/Work/sources/gmp/gmp/usr/app/gmp/lib /usr/app/isl/lib/libisl.la /usr/app/gmp/lib/libgmp.la'
# Libraries that this one depends upon.
dependency_libs=' -L/home/spy/Work/sources/isl/isl/usr/app/isl/lib -L/home/spy/Work/sources/gmp/gmp/usr/app/gmp/lib /home/spy/Work/sources/isl/isl/usr/app/isl/lib/libisl.la /home/spy/Work/sources/gmp/gmp/usr/app/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中的,
当出现这个错误时,我配置成用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
以上就是编译时出现过的有问题的make对象。在makefile文件中,用了下面的rpath即可解决。
-rpath /home/spy/Work/sources/gmp/gmp/usr/app/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/sources/gmp/gmp/usr/app/gmp/lib
就都解决了。
但我发现了另一个方式,把这一个改对就可以
libisl.la: $(libisl_la_OBJECTS) $(libisl_la_DEPENDENCIES) $(EXTRA_libisl_la_DEPENDENCIES)
$(AM_V_CCLD)$(libisl_la_LINK) -rpath /home/spy/Work/sources/gmp/gmp/usr/app/gmp/lib $(libisl_la_OBJECTS) $(libisl_la_LIBADD) $(LIBS)
我不知道这样做是否会出现什么问题,但还没遇到,除了下面没造成什么影响的。
按这个方式修改cloog的makefile的时候,
.la文件中,安装路径里出现的应该是cloog啊,竟然是isl,我做了修改,
# Directory that this library needs to be installed in:
libdir='/home/spy/Work/sources/isl/isl/usr/app/isl/lib'
改成
# Directory that this library needs to be installed in:
libdir='/usr/app/cloog/lib'
------------------------------------------------------------------------------*/
============ [/usr/local] http://gcc.gnu.org/
> gmp,mpfr,mpc,isl,cloog
< bash
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/gcc/gcc-build
$ ../gcc-4.8.2/configure --prefix=/usr/app/gcc --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/sources/gmp/gmp/usr/app/gmp --with-mpfr=/home/spy/Work/sources/mpfr/mpfr/usr/app/mpfr --with-mpc=/home/spy/Work/sources/mpc/mpc/usr/app/mpc --with-isl=/home/spy/Work/sources/isl/isl/usr/app/isl --with-cloog=/home/spy/Work/sources/cloog/cloog/usr/app/cloog
$ make
$ make install DESTDIR=/home/spy/Work/sources/gcc/gcc
--------------------------------------------------------------------------------
gcc就是编译器了,我们编译软件就靠它了,gcc也包含一些库,我们的bash要用到。
gcc的配置选项太多了,我只额外用了
--enable-shared --enable-threads --enable-languages=c
也不知道是否需要。
我编译了50分钟,现在是2014年,我这2手笔记本比较差了,
CPU 1.86GHz,内存2G的,DDR2的,单条1G。
============ http://www.gnu.org/software/bash/
> glibc,gcc
<
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/Bash/bash-build
$ ../bash-4.3/configure --prefix=/usr/app/bash --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi --without-bash-malloc --with-installed-readline
$ make
$ make DESTDIR=/home/spy/Work/sources/Bash/bash install
--------------------------------------------------------------------------------
--without-bash-malloc --with-installed-readline
对这2个不太了解,只是为了bash简单点。
不知道readline干什么的,我构建的系统没有安readline。
--------------------------------------------------------------------------------
在这里推荐个工具,readelf,这是binutils中的一个命令。可查看二进制文件的信息,
我用它主要是为了看到所依赖的库。
$ readelf -hld bin/bash
-a选项是打印所有的信息,我们用-hld就可以了。
看看我们编译后的bash,它需要gcc中的libgcc_s.so.1,而我电脑中的bash却不需要那个库。
--------------------------------------------------------------------------------
有了shell,我们就可以在开发板中验证我们编译的结果了。
至此,我们编译了glibc,gmp,mpfr,mpc,isl,cloog,gcc,bash。
在复制到SD卡之前,我想应该先把mpfr,mpc,isl,cloog中的改动改回来。
根据prefix,将编译后的程序复制到SD卡,/usr/lib/和/usr/bin/中添加相应的软链接。
我并不是在这个时候才制作的软链接,每编译过一个程序,发现有bin和lib文件夹,
就把软链接做好了,直接复制到SD卡中就可以了。
至于怎么制作,我不擅长,写个脚本应该比较好,但我没学。
/etc/中不必有配置文件。
在uEnv.txt中,把bootargs的init改为/usr/bin/bash。
如果就这样启动的话,会提示找不到libgcc_s.so.1,因为这个库不在ld.so的搜索路径中。
目前的搜索路径是/usr/app/glibc/lib。
所以/usr/app/glibc/lib中有个libgcc_s.so.1就可以了,可以放一个软链接,就像/usr/lib中的。
不要担心,这只是临时的。
接下来我们要在开发板中运行ldconfig,这是glibc的一部分,它会读取ld.so.conf文件中的
路径,然后建立一个ld.so.cache文件,这样ld.so就能利用ld.so.cache找到那些路径中的库了。
ld.so.conf文件不存在,而我们构建的系统还没有文本编辑器,所以要在启动之前建立该文件。
内容就是
/usr/lib
很多文本文件都以空行结尾,我们也这么做吧。
那么这个文件要放到哪里呢,一般是/etc/中,但在我们构建的系统中,ldconfig是到
/usr/app/glibc/etc/中找,所以要放到这个目录中。
好,可以启动开发板了,进到shell之后,运行ldconfig。
把/usr/app/glibc/lib中的libgcc_s.so.1删掉,重启,看看是不是可以正常运行了?
这样的方法并不好,应该让编译glibc的时候可以指定ld.so的搜索路径。
其实我当初用了更不好的方法,我在内核参数中指定了LD_LIBRARY_PATH。
虽然我们没安什么程序,但bash是有内置命令的,比如切换目录的'cd',查看
当前目录的'pwd'。
============ http://www.gnu.org/software/coreutils/
>
<
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/coreutils/coreutils-build
也许要先编译一遍本地版的,先看下面的解释。
$ ../coreutils-8.22/configure --prefix=/usr/app/coreutils --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/sources/coreutils/coreutils
--------------------------------------------------------------------------------
--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,而我是交叉编译,目标程序不能
在我的系统中运行。所以我先编译了一遍本地版的,把运行make那个目录中的src文件夹
复制到了'/home/spy/Work/sources/coreutils'。
重新配置成交叉编译,在make之前修改makefile文件,将help2man的目标程序指定到本地版的。
------------------------------------------------------------------------------*/
coreutils里面有我最喜欢的'ls'命令,编译完后,可在开发板中验证下。
============ [/usr] http://linux-pam.org/
>
< util-linux,libcap,
$ cd /home/spy/Work/sources/pam/linux-pam-build
$ ../Linux-PAM-1.1.8/configure --prefix=/usr/app/linux-pam --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work/sources/pam/linux-pam
--------------------------------------------------------------------------------
pam与认证有关,如果没有这个,编译util-linux的时候就不会有login。
util-linux的配置中并没有指定pam的选项,所以安装后,我把pam复制一份
放到我交叉编译器搜索库的目录中了。
我也尝试过把gcc依赖的库放到交叉编译器搜索库的目录中,但遇到了新的问题,
时间关系,没有研究。
pam的库中也有个la文件,根据pam所放的目录,做类似下面的修改。
libpam_misc.la
# Libraries that this one depends upon.
dependency_libs=' /home/spy/Software/arm-2013.11/arm-none-linux-gnueabi/libc/usr/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,里面的函数就这个样子。
------------------------------------------------------------------------------*/
============ ftp://ftp.kernel.org/pub/linux/utils/util-linux/
> pam,ncurses
<
我这里的编译并没有用ncurses,如果你要用的话,可先看看后面我编译ncurses的步骤。
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/util-linux/util-linux-build
$ ../util-linux-2.24.1/configure --prefix=/usr/app/util-linux --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi --without-ncurses
$ make
$ su
# make install DESTDIR=/home/spy/Work/sources/util-linux/util-linux
--------------------------------------------------------------------------------
--without-ncurses
我当初还没编译ncurses,所以加了这个选项,我不知道ncurses是干什么的,这样等以后
出问题的时候就知道它是干什么的了。
/*------------------------------------------------------------------------------
安装时,不能改变bin/wall的用户组为tty
我采用了安装时切换用户为root的方法。
带pam库编译时
cannot find the library `/usr/app/linux-pam/lib/libpam.la' or unhandled argument `/usr/app/linux-pam/lib/libpam.la'
修改libpam_misc.la中的路径,见pam中的修改。
------------------------------------------------------------------------------*/
============ https://sites.google.com/site/fullycapable/
> pam
< systemd,
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
将makefile要引入的文件做如下修改。
CC := arm-none-linux-gnueabi-gcc
BUILD_CC := gcc
AR := arm-none-linux-gnueabi-ar
RANLIB := arm-none-linux-gnueabi-ranlib
LIBATTR := no
$ cd /home/spy/Work/sources/libcap/libcap-2.24
$ make
$ make prefix=/usr/app/libcap lib=lib FAKEROOT=/home/spy/Work/sources/libcap/libcap install
--------------------------------------------------------------------------------
完成以上步骤,复制一份和交叉编译器的库放到一起。
========== [/usr] http://www.freedesktop.org/wiki/Software/systemd/
> libcap
<
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/systemd/systemd-build
修改configure,避免rpl_malloc的错误
if test "$cross_compiling" = yes; then :
ac_cv_func_malloc_0_nonnull=no 改成 yes
$ ../systemd-211/configure --prefix=/usr/app/systemd --with-rootprefix=/usr/app/systemd/root --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi --disable-seccomp --disable-blkid --disable-kmod --disable-pam --disable-libcryptsetup --disable-audit --disable-acl --disable-xattr --disable-selinux --disable-xz --disable-tcpwrap --disable-gcrypt --disable-qrencode --disable-microhttpd --disable-python-devel --without-python --disable-gudev --disable-apparmor --disable-dbus
$ make
$ make install DESTDIR=/home/spy/Work/sources/systemd/systemd
--------------------------------------------------------------------------------
--with-rootprefix=/usr/app/systemd/root
由于安装的时候会有一些东西安装在了app文件夹之外,指定这个选项为安装路径内部就可以了,
root是我随便起的,但最好与其他文件夹独立。
后面那些都是可选的软件包,我全禁用了。
今天一看,竟然有个kmod,我可以告诉你,我构建完的系统好像不能自动载入模块,也许和这个有关吧。
kmod我后面也安了。
--------------------------------------------------------------------------------
编译时看到了很多这样的信息,不知道是什么:
libsystemd_internal_la-bus-message.o (symbol from plugin): warning: memset used with constant zero length parameter; this could be due to transposed parameters
/home/spy/Software/arm-2013.11/arm-none-linux-gnueabi/libc/usr/include/bits/poll2.h: In function 'bus_poll':
/home/spy/Software/arm-2013.11/arm-none-linux-gnueabi/libc/usr/include/bits/poll2.h:71:2: warning: call to '__ppoll_chk_warn' declared with attribute warning: ppoll called with fds buffer too small file nfds entries [enabled by default]
return __ppoll_chk (__fds, __nfds, __timeout, __ss, __bos (__fds));
/*------------------------------------------------------------------------------
配置出错时提示过的
sys/capability.h 在libcap中
pkg-config
intltool
gperf
后3个不是库,编译时被调用,又不像编译器那样为另一个平台生成程序,所以应该不必
为我构建的系统编译他们,用自己Linux系统的包管理器安上就好了。
注意pkg-config是负责寻找库的,如果用他默认的搜索路径,找到的是你正使用系统中的库,
而不是应该用在BeagleBone Black中的库。如果像我这样把那些可选的软件包都禁用的话,
是不需要pkg-config的。我把pkg-config通过配置选项指定到一个目录,也能编译成功。
如果想让pkg-config找到正确的库的话,可看看它的手册,有几个环境变量可影响它搜索库
的路径。
------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
终于到了真正的init程序,这么伟大的程序,竟然没找到学习的文档。我总结了一点。
systemd包含了udev。
--------------------------------------------------------------------------------
At boot time we now print warnings if:
/usr is on a split-off partition but not already mounted by an initrd; if
/etc/mtab is not a symlink to /proc/mounts;
CONFIG_CGROUPS is not enabled in the kernel.
We'll also expose this as tainted flag on the bus.
所以/etc/中应该放个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.
--------------------------------------------------------------------------------
If a process belonging to a specific cgroup fork()s, its child will become a member of the same group.
You can find the cgroups of a process by reading /proc/$PID/cgroup.
cgroups hence make a very good choice to keep track of processes for babysitting purposes.
------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
又到了体验成就感的时候,目前,我们已经拥有的程序,
glibc,gmp,mpfr,mpc,isl,cloog,gcc,bash,
coreutils,linux-pam,util-linux,libcap,systemd。
放到SD卡中。
也许最好把SD卡中文件的用户和组改成root,但是util-linux中的wall属于tty组。
我下面这2条命令是不全的。
# chown -R 0:0
# chgrp -v tty /usr/app/util-linux/bin/wall
由于有了新的程序库,而且是systemd需要用到的,所以先别急着改把init改成systemd,
那样应该会提示找不到库的,所以先用bash,执行一下ldconfig,然后再改,
init=/usr/lib/systemd/systemd
--------------------------------------------------------------------------------
/etc/中的文件,目前就有个mtab,
如果没有passwd文件,会有登陆的提示,还会让输入密码,然后就是登陆失败,所以要创建。
/etc/passwd
root::0:0:root:/home/root:/usr/bin/bash
目前不能设置密码,设置了会登陆失败,不知为什么,可能为了安全吧。所以密码部分空着。
--------------------------------------------------------------------------------
/etc/pam.conf
other auth required pam_unix.so nullok
other account required pam_unix.so broken_shadow
other session required pam_unix.so
other password required pam_unix.so nullok
这是pam的配置文件,可看看pam的手册,内容没深入研究,是我自己看了很多配置后定的。
如果没有配置文件,登陆时会有下面的错误,
login: PAM failure, aborting: Critical error - immediate abort
第一部分是需要pam的程序的名字,如login,改成login也可以。
最后的nullok选项是必要的,这允许没有密码的登陆,也不知道这4个中,哪个需要,
临时先参照别人的。
前面说到,不能在passwd中设置密码,我本以为加了broken_shadow选项就可以了,但不是。
pam也可以在'/etc/pam.d/'中找配置文件,这个是shadow的一部分,里面不止一个配置文件。
如果pam.d存在,则忽略pam.conf。可建个空的pam.d文件夹试试,我没研究。
--------------------------------------------------------------------------------
现在启动BeagleBone Black吧,
systemd启动后,会在/etc/中创建一个machine-id文件,
最后systemd会启动在ttyO0上的登陆服务,提示登陆,输入root,确定后就看见bash了。
我的systemd启动过程中会有一个服务失败,就是在另一个tty设备登陆的服务,可能是我没连
显示器?
一些命令,
显示这次登陆的日志,
# journalctl -b
重启,
$ systemctl reboot
关机
$ systemctl poweroff
但我的关上后,电源指示灯还亮着,别的灯倒是灭了。
------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
曾经没有login时遇到的问题,
localhost login: root
[ 30.279467] systemd[1]: [email protected] has no holdoff time, scheduling restart.
[ 30.314721] systemd[1]: Stopping Serial Getty on ttyO0...
[ 30.321039] systemd[1]: Starting Serial Getty on ttyO0...
[ 30.332073] systemd[1]: Started Serial Getty on ttyO0.
这是systemd的getty服务,在我的系统中该服务调用agetty,看了agetty的手册,
发现它要调用login程序,而此时我构建的系统中没有login程序。
我想表达的是这里没有错误提示。
------------------------------------------------------------------------------*/
============ [/usr/local] http://pkg-shadow.alioth.debian.org/
>
<
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/Shadow/shadow-build
$ ../shadow-4.1.5.1/configure --prefix=/usr/app/shadow --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work/sources/Shadow/shadow
--------------------------------------------------------------------------------
我不太喜欢shadow,因为我不能在那个网站下载到它。
但为了能改密码,还是安了。希望有避免shadow的方法。
shadow中有与已安装程序相同的命令,我选择了shadow中的。
util-linux {login,nologin,su}
coreutils {groups}
它的配置文件要复制一份到/etc/中。
它的配置文件不可以直接用,看看pam.d中的login文件。
内容的格式也就是少了第一部分,这部分用文件名表示了。
奇怪的是你会在配置中发现include,但后面的文件没有。
你也会看到额外的配置,先参照pam.conf改吧。
shadow的login命令会读取login.defs。
登陆的时候,会提示下面这些有问题。
为了不让他们出现,都被我变成注释了。
'FAILLOG_ENAB'
'LASTLOG_ENAB'
'MAIL_CHECK_ENAB'
'OBSCURE_CHECKS_ENAB'
'PORTTIME_CHECKS_ENAB'
'QUOTAS_ENAB'
'MOTD_FILE'
'FTMP_FILE'
'NOLOGINS_FILE'
'ENV_HZ'
'PASS_MIN_LEN'
'SU_WHEEL_ONLY'
'CRACKLIB_DICTPATH'
'PASS_CHANGE_TRIES'
'PASS_ALWAYS_WARN'
'CHFN_AUTH'
'ENVIRON_FILE'
如果你要改密码,那么首先/etc/中要有shadow文件,空的就可以。
-bash-4.3# passwd
Enter new UNIX password:
Retype new UNIX password:
passwd: Authentication token manipulation error
passwd: password unchanged
添加空的shadow文件后
-bash-4.3# passwd
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
/*------------------------------------------------------------------------------
曾经出现过的一些问题
“Login incorrect”
原因提示,
通过passwd改密码;
pam的配置文件没配置好;
有个认证可能需要/etc/shells文件,里面是可用shell的路径。
“Module is unknown”
忘了怎么引起的了。
“Permission denied”
忘了。
------------------------------------------------------------------------------*/
============ [/usr/local] http://www.gnu.org/software/binutils/
>
<
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/binutils/binutils-build
$ ../binutils-2.24/configure --prefix=/usr/app/binutils --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi --target=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work/sources/binutils/binutils
--------------------------------------------------------------------------------
这里面有汇编器,连接器等,我的目的是可以在开发板中构建程序。
LFS的网站上说,这个要在glibc和gcc之前编译,但我是现在编译的,
难道glibc的ld.so可以根据这里的ld确定搜索路径?
============ [/usr/local] http://www.gnu.org/software/make/
>
<
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/make/make-build
$ ../make-4.0/configure --prefix=/usr/app/make --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work/sources/make/make
============ [/usr/local] http://www.gnu.org/software/sed/
>
<
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/sed/sed-build
$ ../sed-4.2.2/configure --prefix=/usr/app/sed --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work/sources/sed/sed
--------------------------------------------------------------------------------
configure脚本中会用到的,还有grep,gawk。
============ [/usr/local] http://www.gnu.org/software/grep/
>
<
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/grep/grep-build
$ ../grep-2.9/configure --prefix=/usr/app/grep --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work/sources/grep/grep
============ [/usr/local] http://www.gnu.org/software/gawk/
>
<
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/gawk/gawk-build
可能还是要先编译一遍本地版的,好像这个错误也没什么问题吧。
而且这样改也不太好。
$ ../gawk-4.1.0/configure --prefix=/usr/app/gawk --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
修改makefile如下
$ make
$ make install DESTDIR=/home/spy/Work/sources/gawk/gawk
/*------------------------------------------------------------------------------
/bin/sh: ../gawk: cannot execute binary file: Exec format error
check-for-shared-lib-support:
@if /home/spy/Work/sources/gawk/gawk.build/build/gawk$(EXEEXT) --version | sed 1q | grep API > /dev/null; \
then : do nothing ; \
else echo Building the extensions is not supported on this platform ; \
exit 1; \
fi
------------------------------------------------------------------------------*/
============ [/usr/local] http://www.gnu.org/software/ncurses/
>
< nano,vim
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/ncurses/ncurses-build
$ ../ncurses-5.9/configure --prefix=/usr/app/ncurses --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi --target=arm-none-linux-gnueabi --with-build-cc=gcc --enable-widec --with-shared
$ make
$ make install DESTDIR=/home/spy/Work/sources/ncurses/ncurses
============ [/usr/local] http://www.nano-editor.org/
> ncurses
<
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/nano/nano-build
好像要修改源文件。
$ ../nano-2.2.6/configure --prefix=/usr/app/nano --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work/sources/nano/nano
/*------------------------------------------------------------------------------
src/nano.h:92:20: fatal error: curses.h: No such file or directory
#elif defined(HAVE_NCURSES_H)
#include
#else
/* Curses support. */
#include
#endif /* CURSES_H */
------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
我在BeagleBone Black中也编译过这个没成功
checking whether build environment is sane... configure: error: newly created file is older than distributed files!
Check your system clock
这是我BeagleBone Black时间的问题。
date -s 20140402
--------------------------------------------------------------------------------
./config.status: line 1095: awk: command not found
安gawk
--------------------------------------------------------------------------------
/bin/install: missing destination file operand after ''
Try '/bin/install --help' for more information.
安装时的错误,短时间内不知如何解决。
------------------------------------------------------------------------------*/
============ [/usr/local] http://www.gnu.org/software/findutils/
>
<
在开发板中编译的,so easy。
安装程序的时候,有时会需要这个,比如下面的vim。
在我的电脑中编译出现以下问题没解决。
stdio.h:749:12: error: expected declaration specifiers or '...' before '(' token
extern int fseek (FILE *__stream, long int __off, int __whence);
^
============ [/usr/local] http://www.vim.org/
> ncurses
<
系统中需要linux header。
# ./configure --prefix=/usr/app/vim --with-tlib=ncursesw
# make
# make install
/*------------------------------------------------------------------------------
checking how to run the C preprocessor... /lib/cpp
configure: error: in `/home/root/vim/vim74/src':
configure: error: C preprocessor "/lib/cpp" fails sanity check
配置时出错。
linux/limits.h: No such file or directory
好像是config.log里的。
好像我把linux header放到开发板中,好了。
linux header参见内核部分。
--------------------------------------------------------------------------------
no terminal library found
checking for tgetent()... configure: error: NOT FOUND!
You need to install a terminal library; for example ncurses.
Or specify the name of the library with --with-tlib.
--with-tlib=ncurses
--------------------------------------------------------------------------------
checking for linking with ncurses library... configure: error: FAILED
--with-tlib=ncursesw
--------------------------------------------------------------------------------
checking size of off_t... configure: error: in `/home/root/vim/vim74/src':
configure: error: cannot compute sizeof (off_t)
See `config.log' for more details.
# ldconfig
--------------------------------------------------------------------------------
./osdef.sh: line 92: diff: command not found
好像是make的时候,没有错误,没有警告。
--------------------------------------------------------------------------------
/bin/sh: find: command not found
这就是安装的时候,暗示你需要findutils。
------------------------------------------------------------------------------*/
好了,现在我们的系统已经可以编译软件了。
虽然还缺少一些必要的软件,如压缩软件。但我构建Linux的目的是研究Linux,构建的思想
已基本掌握,再这样安软件安下去没什么意义了。
为了充分理解构建时遇到的问题,应该学习下更基础的东西了,如
/*
Computer Systems: A Programmer's Perspective
Randal E. Bryant and David R. O'Hallaron, Carnegie Mellon University
*/
如果不看完这本书,我会担心我完成的任务不够完美。
曾经看了一点"Linux Device Drivers",说驱动是了解内核的一个入口。
============ [/usr] ftp://ftp.kernel.org/pub/linux/utils/kernel/kmod/
>
<
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/kmod/kmod-build
$ ../kmod-16/configure --prefix=/usr/app/kmod --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi --disable-manpages
$ make
$ make install DESTDIR=/home/spy/Work/sources/kmod/kmod
--------------------------------------------------------------------------------
编译完的目录中是有一些软链接指向kmod命令的,但安装完的目录里没有那些软链接。
这些软链接很有意思啊,比如insmod指向kmod,输入'insmod',实际运行的不是'kmod',而是
'kmod insmod'。大概是这样的。
kmod与模块有关,所以你的系统中应该放上编译内核时的模块了。
============ [/usr/local] http://libpipeline.nongnu.org/
>
< man-db
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/libpipeline/libpipeline-build
$ ../libpipeline-1.3.0/configure --prefix=/usr/app/libpipeline --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work/sources/libpipeline/libpipeline
============ [/usr/local] http://www.gnu.org.ua/software/gdbm/
>
< man-db
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/gdbm/gdbm-build
$ ../gdbm-1.11/configure --prefix=/usr/app/gdbm --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work/sources/gdbm/gdbm
============ [/usr/local] http://www.nongnu.org/man-db/
> gdbm,libpipeline
<
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/man-db/man-db-build
$ ../man-db-2.6.6/configure --prefix=/usr/app/man-db --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi libpipeline_CFLAGS='-I/home/spy/Work/sources/libpipeline/libpipeline/usr/app/libpipeline/include' libpipeline_LIBS='-L/home/spy/Work/sources/libpipeline/libpipeline/usr/app/libpipeline/lib -lpipeline' --disable-setuid
$ make
$ make install DESTDIR=/home/spy/Work/sources/man-db/man-db
--------------------------------------------------------------------------------
这个程序的README还是值得看看的,我至今未仔细看,所以标记下。
/*------------------------------------------------------------------------------
undefined reference
src/Makefile
manpath$(EXEEXT):
globbing$(EXEEXT):
accessdb$(EXEEXT):
LINK OBJECTS
-rpath /home/spy/Work/sources/libpipeline/libpipeline/usr/app/libpipeline/lib
--------------------------------------------------------------------------------
很遗憾,我没有成功的显示manual,还没时间研究。
------------------------------------------------------------------------------*/
============ [/usr/local] http://www.greenwoodsoftware.com/less/
>
<
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/less/less-build
$ ../less-458/configure --prefix=/usr/app/less --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work/sources/less/less
有了它,journalctl的输出就舒服了。man的输出也是放到less中。
下面的都是与网络有关的了,网络的知识没学,不知道怎么用,可参考下安装过程。
============ [/usr/local/BerkeleyDB.6.0] http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
>
< iproute
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/db/db-build
$ ../db-6.0.30/dist/configure --prefix=/usr/app/db --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi --enable-compat185
$ make
$ make install DESTDIR=/home/spy/Work/sources/db/db
$ make uninstall
$ make clean
$ make realclean
============ [/usr/local] http://www.netfilter.org/projects/iptables/index.html
>
< iproute
$ export PKG_CONFIG_LIBDIR=/home/spy/Software/arm-2013.11/arm-none-linux-gnueabi/libc/usr/lib/pkgconfig
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/iptables/iptables-build
$ ../iptables-1.4.21/configure --prefix=/usr/app/iptables --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work/sources/iptables/iptables
--------------------------------------------------------------------------------
看来我是在这里被迫开始用了pkg-config,要不就是iproute。
============ http://www.linuxfoundation.org/collaborate/workgroups/networking/iproute2
> db(make),iptables(make)
<
ROOTDIR=/home/spy/Software/arm-2013.11/arm-none-linux-gnueabi/libc
PREFIX=/usr/app/iproute
SBINDIR=$(PREFIX)/sbin
CONFDIR=$(PREFIX)/etc/iproute2
CC = arm-none-linux-gnueabi-gcc
HOSTCC = gcc
AR = arm-none-linux-gnueabi-ar
$ export PKG_CONFIG_LIBDIR=/home/spy/Software/arm-2013.11/arm-none-linux-gnueabi/libc/usr/lib/pkgconfig
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ make DESTDIR=/home/spy/Work/sources/iproute/iproute
$ make install DESTDIR=/home/spy/Work/sources/iproute/iproute
--------------------------------------------------------------------------------
IP_CONFIG_SETNS,
TC_CONFIG_IPSET,TC_CONFIG_XT,TC_CONFIG_ATM,TC_CONFIG_XT_OLD,TC_CONFIG_XT_OLD_H,
编译的时候需要pkg-config, bison, flex。
这个程序替代了net-tools,但作为替代品,那个官网可真不怎么好。
它依赖的软件中,我学Arch Linux,在后面括号中标记了make,表示只在编译的时候需要,
虽然不知道Arch Linux是不是这意思。
我确实没有把那2个依赖放到开发版中,iproute可以使用,但不知道有没有什么问题。
============ http://www.zlib.net/
>
< openssh,
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/zlib/zlib-1.2.8
$ CHOST=arm-none-linux-gnueabi ./configure --prefix=/usr/app/zlib
$ make
$ make install DESTDIR=/home/spy/Work/sources/zlib/zlib
============ https://www.openssl.org/
>
< openssh
临时先让系统中的pod2man不可用,见下面解释。
$ ./Configure linux-armv4 --prefix=/usr/app/openssl --cross-compile-prefix=arm-none-linux-gnueabi- shared
$ make
$ make install INSTALL_PREFIX=/home/spy/Work/sources/openssl/openssl
--------------------------------------------------------------------------------
BeagleBone Black是armv7,但配置中没有linux-armv7,倒是有个与android有关的armv7,
那个armv7并没有用与armv7有关的东西,而是armv4的,所以我就用了“linux-armv4”。
有个可疑的zlib-dynamic选项,我没加。
/*------------------------------------------------------------------------------
POD document had syntax errors at /usr/bin/core_perl/pod2man line 71.
看了源码中的pod2mantest,里面说如果系统中没有可用的pod2man,会用openssl中自带的。
既然系统中的有问题,那就用自带的吧。
# mv /usr/bin/core_perl/pod2man /usr/bin/core_perl/pod2man.a
./pod2mantest: line 34: pod2man: command not found
pod2man does not work properly ('BasicTest' failed). Looking for another pod2man ...
No working pod2man found. Consider installing a new version.
As a workaround, we'll use a bundled old copy of pod2man.pl.
------------------------------------------------------------------------------*/
============ [/usr/local] http://www.openssh.com/portable.html
> zlib,openssl
<
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/openssh/openssh-build
$ ../openssh-6.6p1/configure --prefix=/usr/app/openssh --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi --with-zlib=/home/spy/Work/sources/zlib/zlib/usr/app/zlib --with-ssl-dir=/home/spy/Work/sources/openssl/openssl/usr/app/openssl
修改makefile。
$ make
$ make install DESTDIR=/home/spy/Work/sources/openssh/openssh
--------------------------------------------------------------------------------
可疑选项,
--with-pam
--without-shadow
/*------------------------------------------------------------------------------
strip: Unable to recognise the format of the input file
系统中的strip无法识别交叉编译后的程序,看来要用交叉编译器中的。
strip由install调用,看看install的手册,真的有选项可以改变调用的strip,
于是修改makefile,修改install的参数。
STRIP_OPT=-s --strip-program=/home/spy/Software/arm-2013.11/bin/arm-none-linux-gnueabi-strip
--------------------------------------------------------------------------------
sshd: cannot execute binary file
呵,竟然想运行sshd,看看makefile,位于检测的部分,那就别检测了,
删掉install对象中的“check-config”。
------------------------------------------------------------------------------*/
编译完,并没有生成ssh-key,也没提示。
参考了makefiel,在开发板中运行以下命令生成ssh-key。
ssh-keygen -t rsa1 -f /usr/app/openssh/etc/ssh_host_key -N ""
ssh-keygen -t rsa -f /usr/app/openssh/etc/ssh_host_rsa_key -N ""
ssh-keygen -t dsa -f /usr/app/openssh/etc/ssh_host_dsa_key -N ""
ssh-keygen -t ed25519 -f /usr/app/openssh/etc/ssh_host_ed25519_key -N ""
ssh-keygen -t ecdsa -f /usr/app/openssh/etc/ssh_host_ecdsa_key -N ""
============ http://sethwklein.net/iana-etc.html
>
<
$ make PREFIX=/usr/app/iana-etc DESTDIR=/home/spy/Work/sources/iana-etc/iana-etc STRIP=yes
$ make install PREFIX=/usr/app/iana-etc DESTDIR=/home/spy/Work/sources/iana-etc/iana-etc STRIP=yes
不知干什么的,就是些文本文件。
===============================================================================
============ [/usr/local] http://flex.sourceforge.net/
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ cd /home/spy/Work/sources/flex/flex-build
$ ../flex-2.5.39/configure --prefix=/usr/app/flex --build=x86_64-unknown-linux-gnu --host=arm-none-linux-gnueabi
$ make
$ make install DESTDIR=/home/spy/Work/sources/flex/flex
rpl_malloc
if test "$cross_compiling" = yes; then :
ac_cv_func_malloc_0_nonnull=no --> yes
rpl_realloc
if test "$cross_compiling" = yes; then :
ac_cv_func_realloc_0_nonnull=yes
===============================================================================
The major number generally specifies a particular driver within the kernel,
and the minor number specifies a particular device handled by that driver.
===============================================================================
===========
$ export PATH=$PATH:/home/spy/Software/arm-2013.11/bin
$ make CROSS_COMPILE=arm-none-linux-gnueabi- help
$ make CROSS_COMPILE=arm-none-linux-gnueabi- distclean
$ make CROSS_COMPILE=arm-none-linux-gnueabi- allnoconfig
$ make CROSS_COMPILE=arm-none-linux-gnueabi- menuconfig
$ make CROSS_COMPILE=arm-none-linux-gnueabi- all
$ make CROSS_COMPILE=arm-none-linux-gnueabi- CONFIG_PREFIX=../busybox-build install
一开始没用systemd,用的Busybox的init。
===============================================================================
/dev中一些基本的设备,不清楚到底需要什么,也不必考虑了,
因为systemd不需要,但前期我用BusyBox的话,还是要添加的。
# mknod -m 666 null c 1 3
# mknod -m 666 zero c 1 5
# mknod -m 600 console c 5 1
# mknod -m 666 tty c 5 0
# mknod -m 600 tty0 c 4 0
# mknod -m 600 tty1 c 4 1
# mknod -m 600 ttyS0 c 4 64
# mknod -m 600 mem c 1 1
# mknod -m 644 random c 1 8