【问题标题】:Cross compiling c application library referring other libraries symbolically linked交叉编译引用其他符号链接的库的 c 应用程序库
【发布时间】:2020-12-04 09:50:19
【问题描述】:

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

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

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

我也尝试使用 -Wl,-rpath=

command2:

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 => 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)

我使用这个 command1

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

当我尝试使用 objdum -t libnode.so 时,当我尝试通过上述 command2

构建 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

【问题讨论】:

    标签: linux gcc cross-compiling arm-linux


    【解决方案1】:

    链接符号链接没有问题。 这里的问题是链接器正在尝试解析所有引用,因此它需要 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 包含 x.c(其中包含一个函数)和 x.h。
    y.c 包含一个调用 x.c 中的函数的函数。
    z.c 包含一个调用 y.c. 中的函数的函数。

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

    【讨论】:

    • Thaks,但同样的错误。请看上面的帖子。我已经更新了
    • path_to_libgentoo-5.so.100 不得出现在路径中。你能给出你正在使用的确切命令行吗?
    • 更新了一些更简洁的命令和日志
    • 我添加了一个示例。您可以尝试确认它是否在您的机器上工作。它对我的效果很好。
    • 我粘贴了我的 Make 文件,请您提出必要的修改建议。
    【解决方案2】:

    一切看起来都很好,但我注意到您忘记了 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
    

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-10
        • 1970-01-01
        相关资源
        最近更新 更多