0

我正在尝试构建一个依赖于共享库(libnode.so)的应用程序(libnodeapplication),该共享库又依赖于另一个共享库(libgentoo-5.so.100),我将其粘贴在与libnode相同的位置(在 /usr/lib/ 内)

问题是第二个依赖库符号链接到另一个文件

编译命令需要进行哪些更改才能成功构建它(对于在共享库中引用的符号链接文件)

我也尝试使用 -Wl,-rpath=<path to usr/lib/path_to_libgentoo-5.so.100 (也没有文件名):

命令2:

gcc main.o -o libnodeapplication -L/usr/lib/-lnode -Wl,-rpath=/usr/lib/

错误

下面是错误

ld: warning: libgentoo-5.so.100, needed by /usr/lib/libnode.so, not found (try using -rpath or -rpath-link)
usr/lib/libnode.so: undefined reference to `symbol1 in libgentoo-5.so.100'
usr/lib/libnode.so: undefined reference to `symbol2 in libgentoo-5.so.100'
usr/lib/libnode.so: undefined reference to `symbol3 in libgentoo-5.so.100'
.
.
.
and so on

(为简单起见,我使用 gcc 而不是 arm linux 交叉编译器)所以我的最终应用程序是 libnodeapplication,它依赖于共享 lib => libnode.so

libnode.so 正在使用 libgentoo-5.so.100 构建(它存在于 /usr/lib 中并符号链接到 libgentoo-5.so.100.20.0 :libgentoo-5.so.100 -> libgentoo- 5.so.100.20.0)

我使用这个命令1 :

gcc obj1.o obj2.o obj3.o -shared -o libnode.so /usr/lib/libgentoo-5.so.100

当我尝试使用 objdum -t libnode.so 时,当我尝试通过上面的命令 2构建 libnodeapplication 时,我可以找到所有报告为未定义符号的符号

我的 Makefile(用于 libnodeapplication)

CC=<path to tool chain>arm-linux-gnueabihf-gcc
CFLAGS=-Wall
LIB_NAME=-lnode
LIBS=-L$(TARGET_DIR)/usr/lib
INCS=-I./include/

OBJS=libnodeapplication.o

libnodeapplication: $(OBJS)
            $(CC) $(OBJS) -o libnodeapplication $(LIBS) $(LIB_NAME)

main.o: main.c
    $(CC) $(INCS) $(CFLAGS) -c $< -o $@

clean:
    -rm -rf *.o libnodeapplication
    -rm -rf $(TARGET_DIR)/root/libnodeapplication

install:
    cp libnodeapplication $(TARGET_DIR)/root
    chmod +x $(TARGET_DIR)/root/libnodeapplication

为 libnode.so 创建文件

CC=<path to tool chain>arm-linux-gnueabihf-gcc
CFLAGS=-Wall -fPIC
INCS=-I./include/
LIBS=$(TARGET_DIR)/usr/lib/libgentoo-5.so.100
OBJS=libnode.o helper.o

libnode: $(OBJS)
        $(CC) $(OBJS) -shared -o a.so $(LIBS)

libnode.o: libnode.c
        $(CC) $(INCS) $(CFLAGS) -c $< -o $@     

helper.o: helper.c
        $(CC) $(INCS) $(CFLAGS) -c $< -o $@

clean:
        -rm -rf *.o 
        -rm -rf libnode.so
        -rm -rf $(TARGET_DIR)/usr/lib/libnode.so
        -rm -rf $(TARGET_DIR)/usr/include/libnode.h

install:
        -cp libnode.so $(TARGET_DIR)/usr/lib
        -cp libnode.h $(TARGET_DIR)/usr/include
4

3 回答 3

0

您的command1是正确的 - 您只需在command2中使用相同的方式:直接命名库。

命令2: gcc main.o -o libnodeapplication /usr/lib/node.so

完整的工作示例:

$ cat b.c     # (= libgentoo)
int b(int x) {
        return x%4;
}

$ cat a.c     # (= libnode)
int b(int);
int a(int x) {
        return b(x+3);
}

$ cat main.c  # (= nodeapplication)
int a(int);
int main() {
        return a(2);
}

$ pwd
/mounts/compilepartition/a-b-main/
$ mkdir -p ../toomuch  # (Just for fun)
$ gcc -shared -o b.so b.c
$ gcc a.c -shared -o a.so $PWD/b.so
$ gcc main.c -o app /mounts/compilepartition/toomuch/../a-b-main/a.so
$ ldd app
    linux-gate.so.1 (0xf7...)
    /mounts/compilepartition/toomuch/../a-b-main/a.so (0xf7...)
    libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7...)
    /mounts/compilepartition/a-b-main/b.so (0xf7...)
    /lib/ld-linux.so.2 (0x56...)
$ ./app; echo $?
1
$ 

提示:对于交叉编译,您可以隐藏构建路径,例如使用

gcc a.c -shared -o a.so -L /my/complex/build/path -l:b.so

  • 链接时路径/my/complex/build/path/b.so
  • 运行时路径???-> 必须在运行时找到

提示:对于交叉编译,您可以替换您的构建路径,例如

gcc a.c -shared -o a.so -L /my/complex/build/path -l:b.so -W,-rpath=/usr/lib

  • 链接时路径/my/complex/build/path/b.so
  • 运行时路径/usr/lib/b.so

(好吧,这不是替代品,你只是添加一个提示。也许你实际上会得到一个不同的b.so

提示:对于相对于对象/可执行文件的运行时搜索,请使用'$ORIGIN'(用单引号引起来!(在 GNU/Linux 或 GNU/* 中,甚至可能在 Windows 中))

gcc a.c -shared -o a.so -L /my/complex/build/path -l:b.so -W,-rpath='$ORIGIN'/sub

  • 链接时路径/my/complex/build/path/a.so
  • 链接时路径/my/complex/build/path/b.so
  • 运行时路径/usr/lib/a.so(例如)
  • 运行时路径/usr/lib/sub/b.so

(警告:这会变得复杂,因为您可能需要在链接时将子子库存储在所需的相对路径中以链接例如最终可执行文件。)

提示ldd ./a.so:您可以使用or ldd ./app(host=target)查看共享对象和最终可执行文件的加载依赖关系。如果 host!=target 使用strings ./a.sostrings ./app-> 在这里你会看到“b.so”/“a.so”和“/usr/lib”,还有很多神秘的东西。

于 2020-12-13T22:24:20.647 回答
0

一切看起来都很好,但我注意到您忘记了 libnode 的 Makefile 中的 -L 标志

LIBS=$(TARGET_DIR)/usr/lib/libgentoo-5.so.100
=>
LIBS=-L$(TARGET_DIR)/usr/lib/libgentoo-5.so.100

此外,在链接时,您通常不必指定库的完整路径/名称,通常您只会使用标志 -lgentoo。原因是编译器将在 $PATH 中查找名为 'libgentoo.so 的合适库' 这将是您系统上当前使用的任何版本的符号链接,例如

$ls /usr/lib/libgentoo*
/usr/lib/libgentoo.so -> /usr/lib/libgentoo-5.so
/usr/lib/libgentoo-5.so -> /usr/lib/libgentoo-5.so.100
/usr/lib/libgentoo-5.so.100
于 2020-12-08T21:17:59.993 回答
0

链接符号链接没有问题。这里的问题是链接器正在尝试解析所有引用,因此它需要 libgentoo-5.so.100。如果你在生成libnode.so的时候已经使用了libgentoo-5.so.100,可以添加-Wl,-rpath-link=path_to_libgentoo(和libnode的路径一样),就可以了。另一个解决方案可能是在链接可执行文件时也使用 libgentoo-5.so.100。和-l选项-L

有一个极简主义的例子:

all:exec

libx:
    cd xf; \
    arm-linux-gnueabihf-gcc -c $(CFLAGS) -fpic  x.c -I.;\
    arm-linux-gnueabihf-gcc -shared -o libx.so x.o;\
    ln -s libx.so libx.so.10;\

liby:libx
    arm-linux-gnueabihf-gcc -c $(CFLAGS) -fpic y.c -I. -I./xf
    arm-linux-gnueabihf-gcc -shared -o liby.so y.o /home/youssef/test/arm2/xf/libx.so.10

exec:liby
    arm-linux-gnueabihf-gcc $(CFLAGS) -o exec z.c -I. -I./xf -L. -ly -Wl,-rpath=./xf

文件夹 xf 包含 xc (其中包含一个函数), xh
yc 包含一个调用 xc 中的函数的函数
zc 包含一个调用 yc 中的函数的函数

这个例子编译得很好arm-linux-gnueabihf-gcc (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) 7.5.0

于 2020-12-04T18:00:26.340 回答