Home > Mobile >  gcc, how to force the final executable link a unused shared library?
gcc, how to force the final executable link a unused shared library?

Time:07-10

I have an executable shared_main , a shared library libbar.so and a dynamic load shared library libfoo.so (load in shared_main via dlopen).

shared_main doesn't use any symbols from libbar.so but libfoo.so does.

So gcc -g -Wall -o shared_main shared_main.c libbar.so -ldl doesn't link libbar.so to shared_main. Checked via ldd shared_main.

How to let gcc force shared_main link libbar.so?

P.S. I know I can link libfoo.so with libbar.so. But I want to try if I can force shared_main to link libbar.so here.


shared_main.c

#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>

int main(){    
    void* libHandle = dlopen("./libfoo.so", RTLD_LAZY);
    if(libHandle == NULL){
        printf("dlopen:%s", dlerror());
        exit(1);
    }
    int(*xyz)(int);
    xyz = (int(*)(int)) dlsym(libHandle, "xyz");
    if(xyz == NULL){
        printf("dlsym:%s", dlerror());
        exit(1);
    }
    int b = xyz(3);
    printf("xyz(3): %d\n", b);

}

foo.c (libfoo.so)

void func_in_bar();
int xyz(int b){
    func_in_bar();
    return b   10;
}

bar.c (libbar.so)

//mimic python share library runtime
#include <stdio.h>
void func_in_bar(){
    printf("I am a Function in bar\n");
}

void another_func_in_bar(){
    printf("I am another function in bar\n");
}

makefile

shared_main:
    gcc -g -Wall -o shared_main shared_main.c libbar.so -ldl
shared:
    gcc -g -Wall -fPIC -shared -o libfoo.so foo.c
    gcc -g -Wall -fPIC -shared -o libbar.so bar.c

CodePudding user response:

You have an XY-problem, where X is: libfoo has unresolved symbols, but the linker doesn't warn about it

So use the -z defs option linkage-time, and when you get the linker error about the unresolved symbol add -lfoo to the linkage command.

That's still not enough, you will have to use a -L and a -Wl,-rpath option too. Here is a complete Makefile:

# Makefile

# LIBDIR should be the final place of the shared libraries
# such as /usr/local/lib or ~/libexec/myproject

LIBDIR  := ${PWD}
TARGETS := shared_main libbar.so libfoo.so

all: ${TARGETS}

clean:
    rm -f ${TARGETS} 2>/dev/null || true

shared_main: shared_main.c
    gcc -g -Wall -o shared_main shared_main.c -ldl

libbar.so: bar.c
    gcc -g -Wall -fPIC -shared -o libbar.so bar.c

libfoo.so: foo.c libbar.so
    gcc -g -Wall -fPIC -shared -z defs -o libfoo.so foo.c \
    -L${LIBDIR} -Wl,-rpath,${LIBDIR} -lbar

Edit: nonetheless, here is a hackish solution for the original question: use option -Wl,--no-as-needed

shared_main:
    gcc -g -Wall -o shared_main shared_main.c \
    -Wl,--no-as-needed -Wl,-rpath,${PWD} libbar.so -ldl

CodePudding user response:

Everything works just fine for me, with unmodified files from OP.

$ make shared
gcc -g -Wall -fPIC -shared -o libfoo.so foo.c
gcc -g -Wall -fPIC -shared -o libbar.so bar.c

$ make shared_main
gcc -g -Wall -o shared_main shared_main.c libbar.so -ldl

$ LD_LIBRARY_PATH=. ldd shared_main
linux-vdso.so.1 (0x00007ffccb5f2000)
libbar.so => ./libbar.so (0x00007f78f6ce0000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f78f6cd1000)
libc.so.6 => /lib64/libc.so.6 (0x00007f78f6b06000)
/lib64/ld-linux-x86-64.so.2 (0x00007f78f6ce7000)

$ LD_LIBRARY_PATH=. ./shared_main 
I am a Function in bar
xyz(3): 13

I only needed to help the library loader out a bit using LD_LIBRARY_PATH.

$ gcc --version
gcc (GCC) 11.3.1 20220421 (Red Hat 11.3.1-2)
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ ld --version
GNU ld version 2.37-17.fc35
Copyright (C) 2021 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.

CodePudding user response:

The answer is -Wl,--no-as-needed.

For my example, the full command is:

gcc -g -Wall -o shared_main shared_main.c -Wl,--no-as-needed libbar.so -ldl

From https://man7.org/linux/man-pages/man1/ld.1.html :

 --as-needed
 --no-as-needed
           This option affects ELF DT_NEEDED tags for dynamic libraries
           mentioned on the command line after the --as-needed option.
           Normally the linker will add a DT_NEEDED tag for each dynamic
           library mentioned on the command line, regardless of whether
           the library is actually needed or not.  --as-needed causes a
           DT_NEEDED tag to only be emitted for a library that at that
           point in the link satisfies a non-weak undefined symbol
           reference from a regular object file or, if the library is
           not found in the DT_NEEDED lists of other needed libraries, a
           non-weak undefined symbol reference from another needed
           dynamic library.  Object files or libraries appearing on the
           command line after the library in question do not affect
           whether the library is seen as needed.  This is similar to
           the rules for extraction of object files from archives.
           --no-as-needed restores the default behaviour.
  •  Tags:  
  • c gcc
  • Related