问题
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