显式链接本地共享库

时间:2013-04-19 19:38:40

标签: python c gcc makefile centos6

我正在设置Makefile来编译C库的Python包装器。该文件的内容如下(由于信息安全原因,库名称已更改)。行号仅供参考,不包含在文件数据本身中。

  1 CC = gcc                    
  2 CFLAGS = -Wall -fPIC -shared
  3 EXAMPLE_LIB = example
  4 PYTHON = /usr/include/python2.6
  5 LIBS = -L./$(EXAMPLE_LIB) -lexample
  6 INCLUDE = -I./$(EXAMPLE_LIB)/include -I$(PYTHON)
  7 DEPS = test.h
  8 OBJ = test.o
  9 SHARED = test.so
 10 
 11 .PHONY : build
 12 
 13 all: build $(SHARED)
 14 
 15 build:
 16    ./$(EXAMPLE_LIB)/config shared
 17    $(MAKE) -C $(EXAMPLE_LIB)
 18 
 19 %.o: %.c $(DEPS)
 20    $(CC) $(CFLAGS) $(INCLUDE) -c -o $@ $<
 21 
 22 $(SHARED): $(OBJ)
 23    $(CC) $(CFLAGS) $(LIBS) -o $@ $+
 24 
 25 clean:
 26    $(MAKE) clean -C $(EXAMPLE_LIB)
 27    rm $(OBJ)
 28    rm $(SHARED)

EXAMPLE_LIB共享对象文件example.so正在正确编译并存在于<project-directory>/example/example.so,并且<project-directory>/example/include存在第三方库的正确头文件。

我遇到的问题是example.so共享对象库的不同版本(功能较少)安装在全局系统上,而是在我的库(test.so)中链接本地(自编)副本。尝试在Python中导入库时,这会导致undefined symbol错误。

当我使用test.so检查ldd共享对象库时,我看到正在加载/usr/lib64/example.so.1而不是<project-directory>/example/example.so。或者演示:

[mike@tester myproject]$ ldd test.so 
    linux-vdso.so.1 =>  (0x00007fff803ff000)
    example.so.1 => /usr/lib64/example.so.1 (0x00007f98700e8000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f986fd55000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00007f986fb50000)
    libz.so.1 => /lib64/libz.so.1 (0x00007f986f93a000)
    /lib64/ld-linux-x86-64.so.2 (0x0000003afda00000)

是否有可以传递给GCC的选项告诉它明确链接共享对象库的本地版本?

1 个答案:

答案 0 :(得分:4)

问题是-L只是在搜索路径中添加了一个目录,-l只是在搜索路径的任何位置找到了库。所以:

LIBS = -L./$(EXAMPLE_LIB) -lexample
在查看{{1}之前,

...可能会在libexample.solibexample.a/usr/lib等中寻找/usr/local/lib(或/usr/lib64!) }。

有关详细信息,请参阅GCC文档中的Link OptionsOptions for Directory Search

如果要显式指定库,只需将其路径传递给链接器:

./example

正如文档明确指出:

  

使用-l选项和指定文件名之间的唯一区别是-l使用'lib'和'.a'包围库并搜索多个目录。

因此,如果您不希望它搜索多个目录,请不要使用LIBS = ./$(EXAMPLE_LIB)/libexample.so