1

我正在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.so3 方库的正确头文件存在于<project-directory>/example/include.

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

当我使用检查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 的选项来告诉它显式链接共享对象库的本地版本?

4

1 回答 1

4

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

LIBS = -L./$(EXAMPLE_LIB) -lexample

... 可能会在、、等中查找libexample.so(或libexample.a!) ,然后再查找。/usr/lib/usr/local/lib/usr/lib64./example

有关详细信息,请参阅GCC 文档中的链接选项目录搜索选项。

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

LIBS = ./$(EXAMPLE_LIB)/libexample.so

正如文档明确所说:

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

因此,如果您不希望它搜索多个目录,请不要使用-l.

于 2013-04-19T19:49:22.047 回答