source

라이브러리의 여러 버전과 연결

nicesource 2023. 10. 6. 21:44
반응형

라이브러리의 여러 버전과 연결

타사 벤더1의 라이브러리 libfoo 버전 X와 정적으로 연동되는 애플리케이션이 있습니다.또한 VENDER1의 libfoo 버전 Y를 정적으로 연결하는 다른 타사 벤더인 VENDER2의 동적(공유) 라이브러리인 libbar와도 연결됩니다.

그러니까 립바.so는 libfoo.a의 버전 Y를 포함하고 내 실행 파일은 libfoo.a의 버전 X를 포함합니다. libbar는 내부적으로만 libfoo를 사용하고 내 앱에서 libbar로 전달되는 libfoo 객체는 없습니다.

빌드 시에는 오류가 없지만 실행 시에는 앱 세그먼트 장애가 발생합니다.그 이유는 X 버전이 Y 버전과 다른 크기의 구조물을 사용하고 있고 런타임 링커가 어떤 구조물에 의해 사용되는지 섞이는 것 같습니다.

VENDER1과 VENDER2 둘 다 폐쇄적인 소스라 리빌드를 할 수 없습니다.

항상 버전 X로 해결되고 libbar가 항상 버전 Y로 해결되고 둘이 절대 섞이지 않도록 내 앱을 빌드/링크할 수 있는 방법이 있습니까?

답변해 주셔서 감사합니다.효과가 있는 것처럼 보이는 해결책이 있습니다.예를 들어 문제를 자세히 설명해 드리겠습니다.

메인.c는 다음과 같습니다.

#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());
}

Fo.c는 다음과 같습니다.

extern int bar();

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

바에서 우리는 다음을 가지고 있습니다.

#include <stdio.h>

int bar()
{
    printf("bar in bar.c called\n");
    return 2;
}

bar.c 및 fo.c 컴파일:

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

정적 라이브러리에 bar.o 추가:

$ ar r libbar.a bar.o

이제 foo.o를 사용하여 공유 라이브러리를 만들고 정적 libbar.a로 링크합니다.

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

main.c를 컴파일하고 공유 라이브러리 libfoo.so 와 링크합니다.

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

LD_LIBRARY_PATH를 설정하여 libfoo.so 을 찾아 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

공유 라이브러리에 연결된 버전이 아니라 main.c의 bar 버전이 호출됩니다.

메인2.c에는 다음이 있습니다.

#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());
}

main2.c를 컴파일하고 실행합니다(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

이제 공유 라이브러리의 foo calls bar는 공유 라이브러리의 main calls bar는 main.c.

저는 이 행동이 직관적이라고 생각하지 않고 dlopen/dlsym을 사용하는 것이 더 작업적이라고 생각하지만, 제 문제를 해결해 줍니다.

다시 한번 댓글 달아주셔서 감사합니다.

오브젝트 파일 "partial"을 갖도록 partial 링크를 시도합니다.o" libbar와 libfoo-Y와 함께.libffoo-Y local에서 partial.o로 기호를 만들려면 "--localize-symbols"와 함께 objcopy를 사용합니다.libfoo-Y에서 nm를 실행하고 출력을 마사지하여 생성할 수 있어야 합니다.그럼 수정된 partial.o를 가져가서 당신의 앱에 연결해주세요.

저는 vxWorks에서 gcc 툴체인과 유사한 작업을 했습니다. 여기서 동적 립은 복잡하지 않지만 동일한 립의 두 버전이 단일 앱으로 깨끗하게 연결되기 위해 필요합니다.

죄송합니다.리눅스(그리고 아마도 대부분의 *nixes)가 가능하지 않다는 것을 제가 이해합니다.내가 생각할 수 있는 유일한 문제의 '해결책'은 libbar에서 필요한 것을 IPC의 형태로 노출하는 프록시 앱을 만드는 것입니다.그러면 다음을 사용하여 프록시를 올바른 버전으로 로드할 수 있습니다.LD_LIBRARY_PATH아니면 비슷한 것.

언급URL : https://stackoverflow.com/questions/3232822/linking-with-multiple-versions-of-a-library

반응형