我正在设置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的选项告诉它明确链接共享对象库的本地版本?
答案 0 :(得分:4)
问题是-L
只是在搜索路径中添加了一个目录,-l
只是在搜索路径的任何位置找到了库。所以:
LIBS = -L./$(EXAMPLE_LIB) -lexample
在查看{{1}之前, ...可能会在libexample.so
,libexample.a
,/usr/lib
等中寻找/usr/local/lib
(或/usr/lib64
!) }。
有关详细信息,请参阅GCC文档中的Link Options和Options for Directory Search。
如果要显式指定库,只需将其路径传递给链接器:
./example
正如文档明确指出:
使用-l选项和指定文件名之间的唯一区别是-l使用'lib'和'.a'包围库并搜索多个目录。
因此,如果您不希望它搜索多个目录,请不要使用LIBS = ./$(EXAMPLE_LIB)/libexample.so
。