使用 GNU 链接器的正确方法

Posted

技术标签:

【中文标题】使用 GNU 链接器的正确方法【英文标题】:The correct way to use the GNU linker 【发布时间】:2020-08-26 23:35:03 【问题描述】:

我正在尝试在 ubuntu 环境中使用几个库 libglfw3-dev 和 libglew-dev,但无法让链接器执行其预期目的。我通常会使用 makefile,但出于调试目的,我刚刚在 CLI 上使用了 g++。

g++ -I-Iinclude -I/usr/include/GL -I/usr/include/GLFW -L/usr/lib/x86_64-linux-gnu/

我知道我需要使用 -l 标志来指定库本身,但会收到表单错误

/usr/bin/ld: cannot find -llibglfw

这里是一些关于包裹位置的信息(省略不相关的)

root@Jake-Faptop:/usr/include/GLFW# dpkg -L libglfw3-dev
/usr/include/GLFW/glfw3.h
/usr/include/GLFW/glfw3native.h
/usr/lib/x86_64-linux-gnu/libglfw.so
root@Jake-Faptop:/usr/include/GLFW# dpkg -L libglew-dev
/usr/include/GL/glew.h
/usr/include/GL/glxew.h
/usr/include/GL/wglew.h
/usr/lib/x86_64-linux-gnu/libGLEW.so

共享库的名称让我非常困惑,因为它们被命名为 /usr/lib/x86_64-linux-gnu/libGLEW.so.2.1.0/usr/lib/x86_64-linux-gnu/libglfw.so.3.3

---编辑---

根据给出的在库名称上省略前缀和后缀的建议,我仍然在以下输入中遇到链接器错误

g++ -Iinclude -I/usr/include/GL -I/usr/include/GLFW -L/usr/lib/x86_64-linux-gnu/ -lGLEW -lglfw src/main.cpp -o build/main

->

/usr/bin/ld: main.cpp:(.text+0x3b): undefined reference to glfwTerminate'
/usr/bin/ld: main.cpp:(.text+0x54): undefined reference to `glfwWindowHint'
/usr/bin/ld: main.cpp:(.text+0x63): undefined reference to `glfwWindowHint'
/usr/bin/ld: main.cpp:(.text+0x72): undefined reference to glfwWindowHint'

Confused.com...

【问题讨论】:

去掉名字开头的lib 是否也应该省略版本号和 .so 后缀? 是的,您只传递不带lib 且不带后缀(.soa、...)且不带版本的库名称。 【参考方案1】:

删除名称开头的lib。例如。图书馆的名字是

libGLEW.so.2.1.0

链接

-lGLEW

这将链接到libxGLEW.so,这通常是一个符号链接到一个版本库,如libGLEW.so.2.1.0

-图书馆

-l 库

链接时搜索名为 library 的库。 (将库作为单独参数的第二种选择仅用于 POSIX 合规性,不推荐。)

-l 选项由 GCC 直接传递给链接器。有关详细信息,请参阅您的链接器文档。下面的一般描述适用于 GNU 链接器。

链接器搜索库的标准目录列表。搜索的目录包括几个标准系统目录以及您使用 -L 指定的任何目录。

静态库是目标文件的存档,文件名类似于 liblibrary.a。一些目标还支持共享库,通常具有类似 liblibrary.so 的名称。如果同时找到静态库和共享库,则链接器会优先选择与共享库进行链接,除非使用了 -static 选项。

在命令的哪个位置写这个选项会有所不同;链接器按照指定的顺序搜索和处理库和目标文件。因此,“foo.o -lz bar.o”在文件 foo.o 之后但在 bar.o 之前搜索库“z”。如果 bar.o 引用了“z”中的函数,则这些函数可能不会被加载。

https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html

【讨论】:

@JakeO'Neill Try g++ src/main.cpp -o build/main -Iinclude -I/usr/include/GL -I/usr/include/GLFW -L/usr/lib/x86_64-linux-gnu/ -lGLEW -lglfw 我的答案中的最后一段说:“在您编写此选项的命令中有所不同;链接器搜索并处理库和目标文件按照它们指定的顺序。因此,“foo.o -lz bar.o”在文件 foo.o 之后但在 bar.o 之前搜索库“z”。如果 bar.o 引用“z”中的函数,这些函数可能未加载。”

以上是关于使用 GNU 链接器的正确方法的主要内容,如果未能解决你的问题,请参考以下文章

GNU 链接器:适应名称修改算法的更改

软件开发--链接器

非 GNU 链接器是不是有与 GNU 链接器“--just-symbols”选项等效的选项?

链接过程

链接器语法:链接器在链接期间不使用所有链接器的标志

重新排序 gnu autotools 链接器标志