linux 源码[交叉]编译htop

编译htop

介绍

htop是一个Linux下的交互式的进程浏览器,可以用来替换Linux下的top命令。

源码

  • 下载源码

这里选择最新版本2.2.0
下载完成后解压源码,并建立如下相关目录

$ pwd
/opt/htop
$ ls
_build  htop-2.2.0  htop-2.2.0.tar.gz
$ tree
.
├── _build
│   ├── arm-himix200-linux
│   └── ubuntu
├── htop-2.2.0
└── htop-2.2.0.tar.gz
  • 配置源码

进入到源码目录下,执行如下命令,生成configure

$ pwd
/opt/htop/htop-2.2.0
$ ./autogen.sh

编译ubuntu版本

$ pwd
/opt/htop/htop-2.2.0
$ cd ../_build/ubuntu/
$ ../../htop-2.2.0/configure --prefix=`pwd`/install
$ make
  • 出现如下错误:
/usr/bin/ld: Process.o: in function `Process_writeField':
/opt/htop/_build/ubuntu/../../htop-2.2.0/Process.c:473: undefined reference to `minor'
/usr/bin/ld: /opt/htop/_build/ubuntu/../../htop-2.2.0/Process.c:473: undefined reference to `major'
/usr/bin/ld: linux/LinuxProcessList.o: in function `LinuxProcessList_updateTtyDevice':
/opt/htop/_build/ubuntu/../../htop-2.2.0/linux/LinuxProcessList.c:718: undefined reference to `major'
/usr/bin/ld: /opt/htop/_build/ubuntu/../../htop-2.2.0/linux/LinuxProcessList.c:719: undefined reference to `minor'
/usr/bin/ld: /opt/htop/_build/ubuntu/../../htop-2.2.0/linux/LinuxProcessList.c:742: undefined reference to `minor'
/usr/bin/ld: /opt/htop/_build/ubuntu/../../htop-2.2.0/linux/LinuxProcessList.c:746: undefined reference to `major'
/usr/bin/ld: /opt/htop/_build/ubuntu/../../htop-2.2.0/linux/LinuxProcessList.c:742: undefined reference to `major'
/usr/bin/ld: /opt/htop/_build/ubuntu/../../htop-2.2.0/linux/LinuxProcessList.c:746: undefined reference to `minor'
collect2: error: ld returned 1 exit status
make[1]: *** [Makefile:821: htop] Error 1
make[1]: Leaving directory '/opt/htop/_build/ubuntu'
make: *** [Makefile:603: all] Error 2

从网上得知是缺少相关头文件<sys/sysmacros.h>

打开编译出问题的源文件

$ pwd
/opt/htop/htop-2.2.0

$ vim linux/LinuxProcessList.c

#ifdef MAJOR_IN_MKDEV
#include <sys/mkdev.h>
#elif defined(MAJOR_IN_SYSMACROS) || \
   (defined(HAVE_SYS_SYSMACROS_H) && HAVE_SYS_SYSMACROS_H)
#include <sys/sysmacros.h>
#endif

从上面的信息获知有两个宏MAJOR_IN_MKDEVMAJOR_IN_SYSMACROS,结合网上的质料分析应该是后面宏没有开启导致的。

在源码中搜索

$ pwd
/opt/htop/htop-2.2.0

$ ag MAJOR_IN_SYSMACROS
Process.h
13:#elif defined(MAJOR_IN_SYSMACROS) || \

linux/LinuxProcessList.c
31:#elif defined(MAJOR_IN_SYSMACROS) || \

linux/LinuxProcessList.h
13:#elif defined(MAJOR_IN_SYSMACROS) || \

config.h.in
161:#undef MAJOR_IN_SYSMACROS

configure
4945:$as_echo "#define MAJOR_IN_SYSMACROS 1" >>confdefs.h
4957:$as_echo "#define MAJOR_IN_SYSMACROS 1" >>confdefs.h

config.h
162:/* #undef MAJOR_IN_SYSMACROS */

configure.ac
73:   AC_CHECK_HEADER(sys/sysmacros.h, [AC_DEFINE(MAJOR_IN_SYSMACROS, 1,

Process.c
33:#elif defined(MAJOR_IN_SYSMACROS) || \

发现在configure.ac中出现该宏,就推断在configure侦测系统过程中有设置该宏,然后生成config.h文件

打开编译目录下config.h文件

$ pwd
/opt/htop/_build/ubuntu

$ vim config.h

/* Define to 1 if `major', `minor', and `makedev' are declared in
   <sys/sysmacros.h>. */
#define MAJOR_IN_SYSMACROS 1

发现定义了该宏,但是从编译结果上看似乎该宏没有生效。

找到gcc的编译信息

gcc -DHAVE_CONFIG_H -I. -I../../htop-2.2.0  -DNDEBUG  -pedantic -Wall -Wextra -std=c99 -D_XOPEN_SOURCE_EXTENDED -DSYSCONFDIR=\"/opt/htop/_build/ubuntu/install/etc\" -I"../../htop-2.2.0/linux" -rdynamic -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -g -O2 -MT linux/Battery.o -MD -MP -MF $depbase.Tpo -c -o linux/Battery.o ../../htop-2.2.0/linux/Battery.c &&\
mv -f $depbase.Tpo $depbase.Po

发现有三处地方引用的头文件 -I. -I../../htop-2.2.0 -I"../../htop-2.2.0/linux"
第一处是编译目录,后面两处是源码目录。

然后就到源码目录下再次查找MAJOR_IN_SYSMACROS

$ pwd
/opt/htop/htop-2.2.0

$ ag MAJOR_IN_SYSMACROS
Process.c
33:#elif defined(MAJOR_IN_SYSMACROS) || \

Process.h
13:#elif defined(MAJOR_IN_SYSMACROS) || \

configure.ac
73:   AC_CHECK_HEADER(sys/sysmacros.h, [AC_DEFINE(MAJOR_IN_SYSMACROS, 1,

config.h.in
161:#undef MAJOR_IN_SYSMACROS

linux/LinuxProcessList.c
31:#elif defined(MAJOR_IN_SYSMACROS) || \

linux/LinuxProcessList.h
13:#elif defined(MAJOR_IN_SYSMACROS) || \

config.h
162:/* #undef MAJOR_IN_SYSMACROS */

configure
4945:$as_echo "#define MAJOR_IN_SYSMACROS 1" >>confdefs.h
4957:$as_echo "#define MAJOR_IN_SYSMACROS 1" >>confdefs.h

发现在源码目录下也有一个config.h文件,并且该宏没有被定义。

从上面的分析中,可以断定是源码目录下的config.h头文件引起的。
因为此处进行了影子编译,侦测系统生成的config.h文件没有覆盖源码中的config.h文件,
从三处引用头文件的地方,优先使用了源码目录下的config.h文件。

验证上面的猜想,打开LinuxProcessList.Po文件

$ pwd
/opt/htop/htop-2.2.0

$ vim linux/.deps/LinuxProcessList.Po

../../htop-2.2.0/config.h /usr/include/ctype.h /usr/include/features.h \
../../htop-2.2.0/config.h:

从该文件中证实了上面的猜想,删掉源码目录下的config.h文件,继续进行编译。

$ pwd
/opt/htop/htop-2.2.0

$ rm config.h
$ cd ../_build/ubuntu/
$ ../../htop-2.2.0/configure --prefix=`pwd`/install
$ make
$ make install

交叉编译arm-himix200-linux版本

前提是编译好了ncurses,这边把编译好的库放在/opt/htop/_build/arm-himix200-linux/install目录下

$ pwd
/opt/htop/htop-2.2.0
$ cd ../_build/arm-himix200-linux/
$ ../../htop-2.2.0/configure --prefix=`pwd`/install --build=x86_64-linux-gnu --host=arm-himix200-linux CC=/opt/toolchains/hisi-linux/arm-himix200-linux/bin/arm-himix200-linux-gcc CXX=/opt/toolchains/hisi-linux/arm-himix200-linux/bin/arm-himix200-linux-g++ --disable-unicode

出现如下错误

checking for ncurses/curses.h... no
checking ncurses/ncurses.h usability... no
checking ncurses/ncurses.h presence... no
checking for ncurses/ncurses.h... no
checking ncurses.h usability... no
checking ncurses.h presence... no
checking for ncurses.h... no
configure: error: missing libraries:  libncurses

打开config.log查看详细信息

$ pwd
/opt/htop/_build/arm-himix200-linux

$ vim config.log

configure:6097: checking for refresh in -lncurses6
configure:6122: /opt/toolchains/hisi-linux/arm-himix200-linux/bin/arm-himix200-linux-gcc -o conftest -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -g -O2  -Wl,-Bsymbolic-functions -lncurses -ltinfo  conftest.c -lncurses6  -lm  >&5
/home/uname/data/opt/toolchains/hisi-linux/arm-himix200-linux/host_bin/../lib/gcc/arm-linux-gnueabi/6.3.0/../../../../arm-linux-gnueabi/bin/ld: cannot find -lncurses
/home/uname/data/opt/toolchains/hisi-linux/arm-himix200-linux/host_bin/../lib/gcc/arm-linux-gnueabi/6.3.0/../../../../arm-linux-gnueabi/bin/ld: cannot find -ltinfo
/home/uname/data/opt/toolchains/hisi-linux/arm-himix200-linux/host_bin/../lib/gcc/arm-linux-gnueabi/6.3.0/../../../../arm-linux-gnueabi/bin/ld: cannot find -lncurses6
collect2: error: ld returned 1 exit status

configure:6165: checking for refresh in -lncurses
configure:6190: /opt/toolchains/hisi-linux/arm-himix200-linux/bin/arm-himix200-linux-gcc -o conftest -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -g -O2  -Wl,-Bsymbolic-functions -lncurses -ltinfo  conftest.c -lncurses  -lm  >&5
/home/uname/data/opt/toolchains/hisi-linux/arm-himix200-linux/host_bin/../lib/gcc/arm-linux-gnueabi/6.3.0/../../../../arm-linux-gnueabi/bin/ld: cannot find -lncurses
/home/uname/data/opt/toolchains/hisi-linux/arm-himix200-linux/host_bin/../lib/gcc/arm-linux-gnueabi/6.3.0/../../../../arm-linux-gnueabi/bin/ld: cannot find -ltinfo
/home/uname/data/opt/toolchains/hisi-linux/arm-himix200-linux/host_bin/../lib/gcc/arm-linux-gnueabi/6.3.0/../../../../arm-linux-gnueabi/bin/ld: cannot find -lncurses
collect2: error: ld returned 1 exit status

从上面的错误信息中得知,configure会侦测系统两个库libncurses.solibncurses6.so。所以网上有些需要建立ln -s libncurses.so.6.1 libncurses6.so软连接的方法,其实是没有那个必要的。

找不到库文件,增加PKG_CONFIG_PATH配置,重新配置源码

$ pwd
/opt/htop/_build/arm-himix200-linux
$ ../../htop-2.2.0/configure --prefix=`pwd`/install --build=x86_64-linux-gnu --host=arm-himix200-linux CC=/opt/toolchains/hisi-linux/arm-himix200-linux/bin/arm-himix200-linux-gcc CXX=/opt/toolchains/hisi-linux/arm-himix200-linux/bin/arm-himix200-linux-g++ --disable-unicode PKG_CONFIG_PATH=`pwd`/install/lib/pkgconfig

还是出现如上的错误,打开config.log文件查看详细信息

$ pwd
/opt/htop/_build/arm-himix200-linux

$ vim config.log

configure:6165: checking for refresh in -lncurses
configure:6190: /opt/toolchains/hisi-linux/arm-himix200-linux/bin/arm-himix200-linux-gcc -o conftest -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -g -O2  -Wl,-Bsymbolic-functions -lncurses -ltinfo  conftest.c -lncurses  -lm  >&5
/home/uname/data/opt/toolchains/hisi-linux/arm-himix200-linux/host_bin/../lib/gcc/arm-linux-gnueabi/6.3.0/../../../../arm-linux-gnueabi/bin/ld: cannot find -lncurses
/home/uname/data/opt/toolchains/hisi-linux/arm-himix200-linux/host_bin/../lib/gcc/arm-linux-gnueabi/6.3.0/../../../../arm-linux-gnueabi/bin/ld: cannot find -ltinfo
/home/uname/data/opt/toolchains/hisi-linux/arm-himix200-linux/host_bin/../lib/gcc/arm-linux-gnueabi/6.3.0/../../../../arm-linux-gnueabi/bin/ld: cannot find -lncurses
collect2: error: ld returned 1 exit status

从上面的log中发现配置了PKG_CONFIG_PATH,但是没有出现指定的路径。

再次确定PKG_CONFIG_PATH是否配置成功,在config.log中查找

$ pwd
/opt/htop/_build/arm-himix200-linux

$ vim config.log

ac_cv_env_PKG_CONFIG_PATH_set=set
ac_cv_env_PKG_CONFIG_PATH_value=/opt/htop/_build/arm-himix200-linux/install/lib/pkgconfig

从log中发现引用了-ltinfo库,觉得很奇怪,这个库是哪里来的?为什么指定了PKG_CONFIG_PATH,侦测系统时却没有出现相应的路径?

于是开始研究configure生成的过程,看哪里出现了问题

通过如下config.log定位configure

$ pwd
/opt/htop/_build/arm-himix200-linux

$ vim config.log

configure:6131: result: no
configure:6165: checking for refresh in -lncurses

$ cd ../../htop-2.2.0
$ vim vim configure +6131

   if test ! -z "$HTOP_NCURSES_CONFIG_SCRIPT"; then
      # to be used to set the path to ncurses*-config when cross-compiling
      htop_config_script_libs=$($HTOP_NCURSES_CONFIG_SCRIPT --libs 2> /dev/null)
      htop_config_script_cflags=$($HTOP_NCURSES_CONFIG_SCRIPT --cflags 2> /dev/null)
   else
      htop_config_script_libs=$("ncurses5-config" --libs 2> /dev/null)
      htop_config_script_cflags=$("ncurses5-config" --cflags 2> /dev/null)
   fi

发现如上信息,根据上面的注释,如果交叉编译需要指定$HTOP_NCURSES_CONFIG_SCRIPT的路径,否则使用系统的。

做如下实验

$ pwd
/opt/htop/_build/arm-himix200-linux/install/bin

$ ncurses6-config --libs
-Wl,-Bsymbolic-functions -lncurses -ltinfo

$ ./ncurses6-config --libs
-L/home/uname/data/install/hisi-linux/arm-himix200-linux/lib -lncurses

出现可恶的-ltinfo和期望出现的交叉编译路劲了

增加HTOP_NCURSES_CONFIG_SCRIPT配置,重新配置源码

$ pwd
/opt/htop/_build/arm-himix200-linux
$ ../../htop-2.2.0/configure --prefix=`pwd`/install --build=x86_64-linux-gnu --host=arm-himix200-linux CC=/opt/toolchains/hisi-linux/arm-himix200-linux/bin/arm-himix200-linux-gcc CXX=/opt/toolchains/hisi-linux/arm-himix200-linux/bin/arm-himix200-linux-g++ --disable-unicode PKG_CONFIG_PATH=`pwd`/install/lib/pkgconfig HTOP_NCURSES_CONFIG_SCRIPT=`pwd`/install/bin/ncurses6-config
$ make
$ make install

总结

两个大坑,一个是影子编译造成的,一个是使用cnurses库时,需要指定ncurses6-config对应的脚本。

填坑继续中…

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值