我有以下问题:
我有两个独立的c ++项目,并且想在其中一个中使用某些功能。我在Linux上使用g ++进行编译。
我决定通过在项目之外创建一个共享库来使用这些功能来做到这一点。我在Makefile中的编译器标志中添加了-fPIC,然后创建了一个共享库,如下所示:
g++ -shared -Wl,-soname,libmyproject.so.1 -o libmyproject.so a.o b.o c.o -lc
然后,我只需将.so文件和头文件复制到新项目的(父)目录中,并将以下内容添加到其Makefile中:
致LIBS:
-L/../external_proj/libmyproject.so
致CXXFLAGS:
-I/../external_proj
然后我#在目标项目代码中包含适当的头文件,并尝试从原始项目中调用某些函数。但是,当我编译目标项目时,对于导入的函数会出现错误“未定义的引用”。
然后我的问题是:在此设置中我缺少什么?为了导出我要使用的功能,也许需要在原始项目的标题中添加一些内容吗?
我应该注意,这是我第一次尝试以这种方式使用共享库。谢谢。
答案 0 :(得分:1)
-L
标志用于添加 path 以在其中搜索库。-l
(小写L)用于与搜索路径中的库链接。
或者您可以像现在一样跳过标记并直接链接到库(但没有-L
选项)。
如果使用-l
选项,请记住,对于文件libname.so
,仅使用name
作为库名。与-lname
中一样。链接器将搜索带有添加的前缀和后缀的正确文件。
最后,有关链接时使用的路径的重要说明:如果使用-L
和-l
与共享库链接,则只有链接器才能找到该库。如果OS运行时加载程序位于非标准位置,则不能能够查看所使用的路径,并且找不到该库。为此,还必须使用特殊的链接器选项-rpath
设置 runtime-path 。
不幸的是,GCC前端程序g++
无法识别该选项,您必须使用-Wl
来告诉g++
将选项传递给实际的链接程序。与-Wl,-rpath,/path/to/libraries
中一样。
总结一下,这是您可以使用的不同变体:
g++ your_source.cpp ../external_proj/libmyproject.so
-L
和-l
选项:g++ your_source.cpp -L../external_proj -lmyproject
g++ your_source.cpp -L../external_proj -lmyproject -Wl,-rpath,../external_proj
答案 1 :(得分:1)
-L
选项仅指定链接器将在其中搜索要链接的库的 目录 。然后,您将需要使用-l
选项来指定共享库的基本名称(不带“ lib”前缀和“ .so”后缀)。
但是,即使那样也不够。当您尝试尝试执行共享库时,运行时加载器需要找到它。 -L
和-l
足以成功链接,但是默认情况下,运行时加载程序仅搜索/usr/lib(64)?
和其他一些位置。它不搜索当前目录,并且ELF二进制文件仅记录必须加载的共享库的名称,而不记录其完整路径名。您必须明确记录任何其他目录以搜索任何共享库,这是-rpath
选项。
要完成这项工作,您还需要将-rpath
传递给链接器,但是g ++不支持此选项目录,您将必须使用-W
来做到这一点。
您可能需要的全套选项是:
-L/../external_proj -lmyproject -Wl,-rpath -Wl,`cd ../external_proj && pwd`
有关-W
选项的更多信息,请参见gcc文档。
绝对路径名应与-rpath
一起使用,因此需要获取共享库所在目录的完整路径名。