我试图了解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.h
和ncurses_dll.h
的符号链接。也许libncurses.a
文件不是是动态库吗?什么是ncurses.h
呢?
答案 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
是库的真正主标题,应该用于新代码。