现在的位置: 首页 > 综合 > 正文

configure配置调试

2018年01月10日 ⁄ 综合 ⁄ 共 4363字 ⁄ 字号 评论关闭

configure的作用
1.自动进行对目标新系统的猜测过程
现在许多开放源代码的程序都会附带有 configure 脚本。在过去,程序会附带一个 Makefile 文件,这个文件中有 6 个不同的编译标记和选项,但只会用到一个,其余全部注释掉,并且会有一个注解,告诉你“为您的系统选择合适的标记”。如果配置选项更复杂,可能还会有一个名为 config.h 的长长的 C 头文件,其中包含一些要设置的标记,这依赖于主机系统变量。 
第一个方法很简单,在代码中使用 #ifdef 以支持两种系统,例如 BSD 和 System V。由于 Unix 的类型的增加,更为实用的方法是对每一个特性使用 #ifdef 。每个系统的代码如下: 
    #ifdef SUNOS4 || NEXT || NETBSD || FREEBSD || OPENBSD
    #include <string.h>
    #else
    #include <strings.h>
    #endif 
每个特性的代码如下:
    #ifdef HAS_STRING_H
    #include <string.h>
    #else
    #include <strings.h>
    #endif 
后者更容易适应新系统,但需要开发者进行大量的工作。由于现在有太多可能的目标系统,因此,第二种方法对用户来说帮助很大,不仅仅是可以自动生成配置头文件。完成这项任务的一种方法是使用 GNU autoconf 代码来生成 configure 脚本。这个脚本会去执行必要的测试,并创建一个具有适当值的配置头文件。 
2.以一致的方式设置预定义的变量
用手工编辑标记一直存在一个问题,即修改了 Makefile 文件(比如将其安装到 /usr/gnu 而不是 /usr/local 目录下)却忘记修改头文件中相应的值。当然,这样的结果是,编译后的程序不知道到哪里去寻找它们自己的数据文件。使用 configure 脚本的一个好处是可以自动完成一致的安装。 开发人员请注意,一个好的 configure 脚本的另一个好处在于,它会允许用户指定一些个人偏好,例如使用 /usr/gnu 而不是 /usr/local。 
3.完成大量猜测工作
即安装了哪些可选软件包或缺少哪些必要条件。例如,一个设计运行于 X Window System 的程序需要知道 X 安装在哪里,或者甚至要知道是否安装了 X。 
configure 的许多功能实现机制其实很简单。假定想知道 X Windowing System 是否安装在 /usr/X11R6 目录下。一种方法是做一个如下的测试程序: 
#include <X11/X.h> 
int main(void) { return 0; } 
现在,如果用编译器来尝试进行编译,那么只有当 <X11/X.h> 在编译器的 include 路径中时,编译才会成功。因此,对每一个你认为 X 可能安装到的目录,可以将对应的 (directory)/include 加入到编译器的 include 路径中,并尝试对程序进行编译。如果采用某个值时示例文件可以编译,那么就得到了正确的 include 路径。 
请注意在 autoconf 中已经预定义了各种测试程序。如果可能,就直接使用这些测试程序,而不用自己去写。脚本帮那些最需要帮助的人来完成大部分的例行公事的工作。当脚本出错时,引发的额外工作的代价可能不会太大。 
configure的错误解决
既然已经基本上了解了 configure 都做了些什么工作,可以开始寻找错误了。有两种可能的 configure 错误。
    1. configure 是正确的,而系统缺少必要的先决条件。绝大多数情况下, configure 脚本会正确诊断出这种错误。
    2. configure 本身的错误。这样的结果或者是不能生成配置,或者生成一个不正确的配置。 
当 configure 缺少先决条件时,你所要做就是要满足缺少的那些先决条件。找到并安装好后,再重新运行 configure 脚本,就可以成功了。(不要忘记删除 config.cache 文件,这个文件缓存了上一次测试的结果;应该让 configure 从头开始。) 
如果正在开发 configure 脚本,需要确保给出的错误消息有意义。如果测试的是一个函数,而这个函数是一个常见的可添加的软件包的一部分,那么不要告诉用户缺少的函数的名称 —— 告诉用户他们需要的软件包。确保将先决条件信息写入 README 文件中。并且,请一定要告诉人们您测试使用的其他软件包的版本号。 
当然,即使在先决条件需要的软件安装以后,configure 脚本可能还是找不到新安装的程序。怎么办呢?
configure -h
无论何时,当 configure 失败时您首先要做的是运行 configure -h ,并检查参数列表。
如果它找不到确认已经安装的库,可以指定到另一个位置来找到这个库,还可以禁用和启用某些特性。
例如,用于 Angband (一个 Roguelike 游戏)的 configure 脚本有一个可选的标记 —— enable-gtk ,以告诉脚本在编译时启用 GTK 支持。如果没有这个标记,编译时根本不会去尝试。 
假如你的系统配置比较奇怪,那就要为configure脚本配置详细的变量了。比如交叉编译,CC 是 configure 用于指定 C 编译器的变量,通过指定 CC 的值可以解决许多问题。要注意的是,这样可以在命令行中指定选项和标记。例如,如果希望编译时支持调试符号,尝试: 
CC="gcc -g -O1" ./configure 
(这里假定使用的是 sh 系列的 shell;在 csh 中,用 setenv 来设置环境变量 CC 。) 
阅读 config.log
当 configure 脚本运行时,它会创建一个名为 config.log 的文件,其中记录的是测试日志和得到的结果。例如,一个典型的 config.log 片断如下: 
    configure:2826: checking for getpwnam in -lsun
    configure:2853: gcc -o conftest -g -O2 -fno-strength-reduce conftest.c -lsun >&5
    ld: cannot find -lsun
    configure:2856: $? = 1
    configure: failed program was:
    (a listing of the test program follows)
 
如果我的系统中, -lsun 应该提供 getpwnam() ,我应该可以使用命令行来对其进行确切检查,然后再使用测试程序。只需进行少量这样的调试,我就可以根据得到的信息来修改 configure 脚本。请注意有帮助的行号;这个测试从 configure 脚本的第 2,826 行开始。(如果您是一个 shell 程序员,您可能会喜欢在阅读 configure 脚本片断时打印出行号;在 shell 中 $LINENO 不能自动地被扩展为合理值,脚本使用 sed 创建一个包含有行号的自身拷贝!) 
当一个测试失败或者得到意外的结果时,最好先去读一读日志文件。请注意,有时测试失败仅仅是因为上一个测试的失败,这种失败实际上并不重要。例如, configure 可能会因为找不到一个您闻所未闻的库而退出,而这可能是因为测试标准 C 库中某个功能的程序失败而导致无法找到那个库。在这种情况下,只需要解决第一个问题,第二个问题也就不会再出现了。 
找到缺少的库和 include
使用 configure 脚本的另一个常见的问题是,如果一个特定的软件包安装到了一个非常规的位置, configure 将无法找到它。好的 configure 脚本通常允许您指定所需要的文件的路径,因为它们可能被安装到与众不同的位置。例如,许多 configure 脚本用一个标准的方法来告诉脚本到何处去寻找 X 库: 
    X features:
      --x-includes=DIR    X include files are in DIR
      --x-libraries=DIR   X library files are in DIR
 
如果这样仍不行,您还可以尝试使用完全强制的方法:指定需要的编译器标记为您的 CC 环境变量或者是 CFLAGS 环境变量的一部分。 
有 bug 的测试程序(极少出现)
在其他一些情况下, configure 可能会偶而出现猜测错误。一种情况是测试程序设计不正确而可能在一些系统中编译失败。例如,考虑如下用于判断 strcmp() 函数可用性的测试程序: 
    extern int strcmp();
    int main(void) {
                    strcmp();
    } 
编写这个程序是为了避免使用 <string.h> 头文件。这样做的意图是,如果 strcmp() 在库中可以找到,程序将可以被正确地编译和链接;如果没有找到,链接器将不能解析到 strcmp() 的引用,程序编译就会失败。 
在 UnixWare 编译器的某一个版本中,对 strcmp() 的引用被自动转换为 Intel 处理器自己的字符串比较指令。这个过程只是将传递到 strcmp() 的参数替换到一行汇编代码中。不幸的是,前面的例子程序调用 strcmp() 时没有给出参数,因此生成的汇编代码无效,从而导致编译失败。实际上是可以使用系统中的 strcmp() ,但是测试程序错误地认为缺少这个函数。 
当 autoconf 的目标为主流平台(特别是各种 Linux,但是还包括主要的 Unix 发行版本)时,极少出现有 bug 的测试,这种有 bug 的测试通常是在那些没用被广泛测试过的平台或编译器上运行测试的结果。例如,UnixWare 上的 gcc 不会发生前面的 bug;只是在使用系统本身的开发包进行编译时才会发生。通常,最简单的解决办法是在 configure 中注释掉相应的测试,并直接设置出问题的环境变量。 

其他
假如你经常使用configure命令,可以写一个与下面类似的脚本: 
    ./configure --with-package=/path/to/package \
       --enable-widget \
       --disable-gizmo \
       --with-x=29 \
       --with-blah-blah-blah
       CFLAGS="-O1 -g -mcpu=i686 -L/usr/unlikely/lib \
          -I/usr/unlikely/include -Wl,-R/usr/unlikely/lib" 
相对于一遍又一遍地在命令行中输入,将脚本放在一起将很方便 —— 而且以后还可以引用它,或者将它的一个拷贝寄给别人。
开发:
1.不要去测试那些你并不真正需要的内容。
2.尽量确保使用最新版本的autoconf。
 

抱歉!评论已关闭.