|
楼主 |
发表于 2002-11-30 17:27:04
|
显示全部楼层
第一次编译bash-2.05a时,编译失败,出现提示:
gcc -s -DPROGRAM='"bash"' -DCONF_HOSTTYPE='"i686"' -DCONF_OSTYPE='"linux-gnu"' -DCONF_MACHTYPE='"i686-pc-linux-gnu"' -DCONF_VENDOR='"pc"' -DSHELL -DHAVE_CONFIG_H -I. -I. -I./include -I./lib -g -O2 -c shell.c
In file included from shell.h:41,
from shell.c:48:
externs.h:163: conflicting types for `gethostname'
/usr/include/unistd.h:734: previous declaration of `gethostname'
externs.h:196: conflicting types for `strncasecmp'
/usr/include/string.h:277: previous declaration of `strncasecmp'
make: *** [shell.o] Error 1
当时就把我给吓一跳。后来冷静地看了错误提示,发现是函数类型冲突,于是打开shell.c,发现第48行为externs.h。看来是externs.h的问题。于是以打开externs.h,在第163行找到gethostname的函数定义:
extern int gethostname __P((char *, int));
再到/usr/include/unistd.h中找到gethostname的函数定义:
extern int gethostname (char *__name, size_t __len) __THROW;
两相比较,发现这两函数是不一样。我虽然学习过linux下的C编程,但象这么复杂的函数定义还是第一次看到,查书也找不到到__P和__THROW是什么意思。size_t的宏定义我没有找到,但在/usr/include/bits/types.h中和/usr/include/sys/types.h中ssize_t的宏定义都是int,所以我想size_t应该与ssize_t差不多,也是int。经过反复考虑,决定先把参数类型变为一致。于是将externs.h中的gethostname函数定义中的int改为size_t,即:
extern int gethostname __P((char *, size_t));
重新编译,出来一堆错误提示,仔细看看,没有gethostname的问题,剩下strncasecmp的错误提示。看来这招管用,继续对比strncasecmp的函数定义,也是一样的问题,照此办理后,以出来一堆错误提示,但没有发现这两个问题的错误提示重复出现,应该说是成功解决。其它类似的情况我就不说了。
但是,这招碰到下面这个问题就不灵了。
make[1]: Entering directory `/mnt/lfs/static/src/bash-2.05a/builtins'
rm -f mkbuiltins.o
gcc -s -c -DHAVE_CONFIG_H -DSHELL -I. -I.. -I.. -I../include -I../lib -I. mkbuiltins.c
mkbuiltins.c:136: warning: static declaration for `rename' follows non-static
mkbuiltins.c: In function `rename':
mkbuiltins.c:1425: argument `from' doesn't match prototype
mkbuiltins.c:136: prototype declaration
mkbuiltins.c:1425: argument `to' doesn't match prototype
mkbuiltins.c:136: prototype declaration
make[1]: *** [mkbuiltins.o] Error 1
make[1]: Leaving directory `/mnt/lfs/static/src/bash-2.05a/builtins'
make: *** [builtins/builtext.h] Error 1
打开/mnt/lfs/static/src/bash-2.05a/builtins下的mkbuiltins.c文件,发现第136行的rename的函数定义为:
static int rename ();
而1423行开始的rename函数为:
- static int
- rename (from, to)
- char *from, *to;
- {
- unlink (to);
- if (link (from, to) < 0)
- return (-1);
- unlink (from);
- return (0);
- }
复制代码
我左看右看,怎么也看不出有什么错误。因为在同一个函数内部,所有函数都采用类似的定义,如is_special_builtin ()的定义方式:
static int is_special_builtin ();
和它的内容:
- static int
- is_special_builtin (name)
- char *name;
- {
- return (_find_in_table (name, special_builtins));
- }
复制代码
与rename相比是一样的。没有办法,只好先按照经验,让函数声明和类型保持一致。将rename函数声明改为:
static int rename (char *,char *);
编译,出现错误提示:
make[1]: Entering directory `/mnt/lfs/static/src/bash-2.05a/builtins'
rm -f mkbuiltins.o
gcc -s -c -DHAVE_CONFIG_H -DSHELL -I. -I.. -I.. -I../include -I../lib -I. mkbuiltins.c
mkbuiltins.c:137: conflicting types for `rename'
/usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.2/include/stdio.h:153: previous declaration of `rename'
make[1]: *** [mkbuiltins.o] Error 1
make[1]: Leaving directory `/mnt/lfs/static/src/bash-2.05a/builtins'
make: *** [builtins/builtext.h] Error 1
在/usr/lib/gcc-lib/i586-mandrake-linux-gnu/3.2/include/stdio.h第153行找到rename函数,其定义为:
extern int rename (__const char *__old, __const char *__new) __THROW;
与mkbuiltins.c的相比较,看不出应该改什么地方。从mkbuiltins.c中的rename()函数的定义来看,前面加有static字样,应该是一个局部函数的声明,即使与其它函数重名也应该没有关系,怎么会编译出错?迫于无奈,只好将mkbuiltins.c中的rename()函数改名为rename1(),编译后仍然出现一堆错误。看来是山穷水尽没有办法了。由于当时我已经感到很烦也很没希望,所以下面的错误提示我没有记录。我真的是感到有点后悔,不应该这么冒失,早知道装LFS这么麻烦,不如干点别的。我到外面转了转,感觉心情好点之后,再回到计算机前,仔细看看提示,发现有ld找不到-lc字样。学过编程的都知道-lc是一种简略写法,表示标准库/usr/lib下的libc.a文件,我到/usr/lib下一看,果然没有libc.a文件,只有一个libc.so文件,于是进入mandrake控制中心,以libc搜索没有安装的软件包,把所有找到的软件包(共有44M)全部安装。安装后,果然在/usr/lib下有了一个libc.a文件。再编译,还是一堆错误,不过内容变了。好象是提示rename1()没有定义之类的,看来刚才修改的函数名还得再改回去,真是让人啼笑皆非,改完之后,再编译,终于成功。看来这个问题实际上是缺少函数链接库造成的,编译器可能在什么地方需要间接调用这个函数库,却不能给出明确的提示,结果让人大伤脑筋。 |
|