Cross compiling c application library referring other libraries symbolically linked

99封情书 提交于 2021-01-29 08:17:08

问题


I am trying to build an application(libnodeapplication) which is dependent on a shared library(libnode.so) which in turn depends on another shared library(libgentoo-5.so.100) which I have pasted at the same location as the libnode(inside /usr/lib/)

Problem is second dependent library is symbolically linked to another file

what changes are needed in the compile command to build it successfully(for symbolically linkd files refrened in the shared library)

I tried with -Wl,-rpath=<path to usr/lib/path_to_libgentoo-5.so.100 (also without file name) as well :

command2 :

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

error

below is the error

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

(for simplicity i have used gcc instead of arm linux cross compiler) so my end application is libnodeapplication which depends on shared lib => libnode.so

libnode.so is being built using the libgentoo-5.so.100 (which is present in the /usr/lib and symbolically linked to libgentoo-5.so.100.20.0 : libgentoo-5.so.100 -> libgentoo-5.so.100.20.0)

I use this command1 :

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

When i try to use the objdum -t libnode.so , I can find all those symbols which are reported as undefined symbols when I try to build the libnodeapplication by above command2

My Makefile(for 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

Make file for 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

回答1:


There is no problem to link against symbolic links. The problem here is that the linker is trying to resolve all the references, so it needs libgentoo-5.so.100. If you have already used libgentoo-5.so.100 when generating libnode.so, you can add -Wl,-rpath-link=path_to_libgentoo (which is the same as the path for libnode) and it will work. An other solution could be to also use libgentoo-5.so.100 when linking the executable. with -l and -L options.

there is a minimaliste exemple:

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

the folder xf contain x.c ( which contain one function ) and x.h.
y.c contain one function which call the function in x.c.
z.c contain one function which call the function in y.c.

This example compile well with arm-linux-gnueabihf-gcc (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) 7.5.0




回答2:


Everything looks fine, but I noticed you forgot the -L flag in the Makefile for libnode

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

Also when linking you usually don't have to specify the full path/name of your library, Usually you would go only with the flag -lgentoo The reason is the compiler will look in $PATH for a suitable library that will be named 'libgentoo.so' wich will be a sym link to whatever version is currently used on your system, for example

$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:


Your command1 was right - you just have to use the same way in command2: name the library directly.

command2: gcc main.o -o libnodeapplication /usr/lib/node.so

Full working example:

$ 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
$ 

Tip: For cross compiling, you can hide your build path, e.g. with

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

  • Link-time path /my/complex/build/path/b.so
  • Run-time path ??? -> must be found at runtime

Tip: For cross compiling, you can replace your build path, e.g. with

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

  • Link-time path /my/complex/build/path/b.so
  • Run-time path /usr/lib/b.so

(OK, it's no replacement, you're just adding a hint. Maybe you will actually get a different b.so)

Tip: For runtime searching relative to the object/executable, use '$ORIGIN' (quoted in single quotes! (in GNU/Linux or GNU/*, probably even in Windows))

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

  • Link-time path /my/complex/build/path/a.so
  • Link-time path /my/complex/build/path/b.so
  • Run-time path /usr/lib/a.so (for instance)
  • Run-time path /usr/lib/sub/b.so

(Warning: this gets complicated because you may need to store the sub-sub-libraries in the required relative path at link-time for linking e.g. a final executable.)

Tip: You can look on shared objects' and final executables' load dependencies with ldd ./a.so or ldd ./app (host=target). If host!=target use strings ./a.so or strings ./app -> here you see "b.so"/"a.so" and "/usr/lib", amongst lots of cryptic stuff.



来源:https://stackoverflow.com/questions/65141336/cross-compiling-c-application-library-referring-other-libraries-symbolically-lin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!