【问题标题】:Explicitly linking a local shared object library显式链接本地共享对象库
【发布时间】:2013-04-13 07:13:09
【问题描述】:

我正在设置一个 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 正在正确编译并存在于&lt;project-directory&gt;/example/example.so 中,并且第三方库的正确头文件存在于&lt;project-directory&gt;/example/include。

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

当我使用ldd 检查test.so 共享对象库时,我看到正在加载/usr/lib64/example.so.1 而不是&lt;project-directory&gt;/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 以告诉它显式链接本地版本的共享对象库吗?

【问题讨论】:

    标签: python c gcc makefile centos6


    【解决方案1】:

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

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

    ...在查看./example 之前,可能会在/usr/lib、/usr/local/lib、/usr/lib64 等中寻找libexample.so(或libexample.a!)。

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

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

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

    正如文档明确所说:

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

    所以,如果您不想让它搜索多个目录,请不要使用-l。

    【讨论】:

    • 我对GCC的理解不是特别强。在上面的示例中,将LIBS = -L./$(EXAMPLE_LIB) -lexample 更改为LIBS = ./$(EXAMPLE_LIB)/libexample.so 是否可以工作,还是我需要使用某个选项?
    • 是的,这正是我的意思。抱歉没有更清楚。希望编辑后的答案更好?
    • 在我的特殊情况下我仍然有链接问题,但这个答案似乎解释了我问题的症结。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-26
    • 1970-01-01
    • 2018-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-25
    相关资源
    最近更新 更多