这些不同的gcc链接选项如何更改最终的可执行文件?

时间:2013-10-28 21:11:33

标签: c linux gcc linker ncurses

我试图了解gcc中的库和链接是如何工作的。我正在尝试从文件test.c编译an example ncurses“Hello World”程序:

#include <ncurses.h>

int main()
{
    initscr();                      /* Start curses mode              */
    printw("Hello World !!!");      /* Print Hello World              */
    refresh();                      /* Print it on to the real screen */
    getch();                        /* Wait for user input */
    endwin();                       /* End curses mode                */

    return 0;
}

我首先使用此命令编译它(没有makefile):

gcc test.c -o test.exe -lncurses

这产生了一个9kb的文件。在不了解-lncurses开关的作用之后,我读了一些关于链接的内容,然后是关于静态和动态的内容,并决定我想尝试静态地编译la here

gcc -static test.c -o test.exe -lncurses

但是,由于某种原因,这不起作用,并产生了大量ld未定义的对x'错误的引用。例如:

/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libncurses.a(lib_echo.o): In function `echo':
(.text+0x3): undefined reference to `SP'

从其他地方,我添加了-L/usr/lib选项:

gcc -static test.c -o test.exe -L/usr/lib -lncurses

这创建了一个更大的文件,1103kb 我能理解为什么那应该更大。 我不明白为什么只删除-static选项:

gcc test.c -o test.exe -L/usr/lib -lncurses

...生成一个184kb的文件,即使它没有静态链接到ncurses库。

-L / usr / lib选项在这里做什么?根据{{​​3}},它将目录“添加到要搜索的目录列表-l ”。 / usr / lib目录包含libncurses.a文件(以及其他文件),而/ usr / include包含ncurses.h符号链接到curses.hncurses_dll.h的符号链接。也许libncurses.a文件不是是动态库吗?什么是ncurses.h呢?

1 个答案:

答案 0 :(得分:3)

这很可能是您想要构建它的方式:

gcc test.c -o test -lncurses

这说:“编译test.c,命名输出文件test并动态链接名为libncurses.so的库(或共享对象)(lib前缀自动添加)。

请注意,.exe后缀未在Linux上使用,仅用于Windows(您的问题标有linux,因此我认为这是您在此处使用的平台。)

如果你像这样静态链接:

gcc -static test.c -o test.exe -lncurses

然后链接器将查找库的静态版本(即。libncurses.a)。您会收到大量链接器错误,因为它无法解析对库函数的引用,这表明您没有库的静态版本。除非你有一个非常好的理由静态链接,否则标准是使用动态链接。

下一个命令只是指定了一些额外的(但是冗余的)库路径:

gcc -static test.c -o test.exe -L/usr/lib -lncurses

这只是告诉链接器在查找库时搜索/usr/lib。但是,/usr/lib已经在默认路径中,因此通常不会产生影响。如果您运行gcc -dumpspecs,它将打印已经“烘焙”到工具中的所有路径和定义,从而打印包含文件,库等的默认搜索路径。

  

在/ usr / lib目录具有libncurses.a文件(主要),同时在/ usr /包括含有一个ncurses.h符号链接到curses.h和ncurses_dll.h。也许libncurses.a文件不是动态库?什么是ncurses.h呢?

符号链接用于向后兼容。 ncurses库(用于“新curses”)取代原始curses,但提供curses.h旧代码仍然可以构建和运行。 ncurses_dll.h标题提供了一些仅用于在Windows下编译cygwin或MSVC的定义,因此您可以忽略它。 ncurses.h是库的真正主标题,应该用于新代码。