Linking with multiple versions of a library

前端 未结 3 1779
没有蜡笔的小新
没有蜡笔的小新 2020-12-13 02:34

I have an application that statically links with version X of a library, libfoo, from thirdparty vendor, VENDOR1. It also links with a dynamic (shared) library, libbar, from

相关标签:
3条回答
  • 2020-12-13 03:21

    Thanks for all the responses. I have a solution that seem to be working. Here's the problem in detail with an example.

    In main.c we have:

    #include <stdio.h>
    
    extern int foo();
    
    int bar()
    {
        printf("bar in main.c called\n");
        return 0;
    }
    
    int main()
    {
        printf("result from foo is %d\n", foo());
        printf("result from bar is %d\n", bar());
    }
    

    In foo.c we have:

    extern int bar();
    
    int foo()
    {
        int x = bar();
        return x;
    }
    

    In bar.c we have:

    #include <stdio.h>
    
    int bar()
    {
        printf("bar in bar.c called\n");
        return 2;
    }
    

    Compile bar.c and foo.c:

    $ gcc -fPIC -c bar.c
    $ gcc -fPIC -c foo.c
    

    Add bar.o to a static library:

    $ ar r libbar.a bar.o
    

    Now create a shared library using foo.o and link with static libbar.a

    $ gcc -shared -o libfoo.so foo.o -L. -lbar
    

    Compile main.c and link with shared library libfoo.so

    $ gcc -o main main.c -L. -lfoo
    

    Set LD_LIBRARY_PATH to find libfoo.so and run main:

    $ setenv LD_LIBRARY_PATH `pwd`
    $ ./main
    bar in main.c called
    result from foo is 0
    bar in main.c called
    result from bar is 0
    

    Notice that the version of bar in main.c is called, not the version linked into the shared library.

    In main2.c we have:

    #include <stdio.h>
    #include <dlfcn.h>
    
    
    int bar()
    {
        printf("bar in main2.c called\n");
        return 0;
    }
    
    int main()
    {
        int x;
        int (*foo)();
        void *handle = dlopen("libfoo.so", RTLD_GLOBAL|RTLD_LAZY);
        foo = dlsym(handle, "foo");
        printf("result from foo is %d\n", foo());
        printf("result from bar is %d\n", bar());
    }
    

    Compile and run main2.c (notice we dont need to explicitly link with libfoo.so):

    $ gcc -o main2 main2.c -ldl
    $ ./main2
    bar in bar.c called
    result from foo is 2
    bar in main2.c called
    result from bar is 0
    

    Now foo in the shared library calls bar in the shared library and main calls bar in main.c

    I don't think this behaviour is intuitive and it is more work to use dlopen/dlsym, but it does resolve my problem.

    Thanks again for the comments.

    0 讨论(0)
  • 2020-12-13 03:30

    Try a partial link so that you have an object file "partial.o" with libbar and libfoo-Y. Use objcopy with "--localize-symbols " to make the symbols in partial.o from libfoo-Y local. You should be able to generate by running nm on libfoo-Y and massaging the output. Then take the modified partial.o and link it to your app.

    I've done something similar with gcc toolchain on vxWorks where dynamic libs are not a complication but two versions of the same lib needed to link cleanly into a monolithic app.

    0 讨论(0)
  • 2020-12-13 03:31

    Sorry no. My understanding of the way that Linux (and possibly most *nixes) is that that is not possible. The only 'solution' for your problem I can think of, is if you create a proxy app, which exposes what you need from libbar in the form of some IPC. You can then make that proxy load the correct version using LD_LIBRARY_PATH or something simmilar.

    0 讨论(0)
提交回复
热议问题