programing tip

종속성이있는 동적 라이브러리와 연결

itbloger 2020. 11. 9. 07:54
반응형

종속성이있는 동적 라이브러리와 연결


다음 시나리오를 고려하십시오.

  • 종속성이없는 공유 라이브러리 libA.so.
  • 종속성으로 libA.so를 사용하는 공유 라이브러리 libB.so.

libB와 연결되는 바이너리 파일을 컴파일하고 싶습니다. 바이너리를 libB 와만 ​​연결해야합니까? 아니면 libA와 연결해야합니까?

런타임에 대한 종속성에서 해결되지 않은 기호를 해결할 수 있도록 직접 종속성과 만 연결하는 방법이 있습니까?

라이브러리 libB 구현이 향후 변경되어 다른 종속성 (예 : libC, libD, libE)을 도입 할 수 있다는 사실이 걱정됩니다. 그게 문제가 될까요?

다시 말해:

  • libA 파일 : a.cpp ah
  • libB 파일 : b.cpp bh
  • 주 프로그램 파일 : main.cpp

물론 b.cpp에는 ah가 포함되고 main.cpp에는 bh가 포함됩니다.

컴파일 명령 :

g++ -fPIC a.cpp -c
g++ -shared -o libA.so a.o

g++ -fPIC b.cpp -c -I.
g++ -shared -o libB.so b.o -L. -lA

다음 중 어떤 옵션을 사용해야합니까?

g++ main.cpp -o main -I. -L. -lB

또는

g++ main.cpp -o main -I. -L. -lB -lA

첫 번째 옵션을 사용할 수 없습니다. 링커는 라이브러리 libA의 해결되지 않은 기호에 대해 불평합니다. 하지만 좀 이상하게 들립니다.

매우 감사합니다.

-업데이트 된 댓글 :

바이너리를 연결할 때 링커는 main 및 libB의 모든 기호를 확인하려고합니다. 그러나 libB에는 libA의 정의되지 않은 기호가 있습니다. 이것이 링커가 그것에 대해 불평하는 이유입니다.

그래서 libA 와도 연결해야합니다. 그러나 공유 라이브러리에서 해결되지 않은 기호를 무시하는 방법을 찾았습니다. 다음 명령 줄을 사용하여 수행해야하는 것 같습니다.

g++ main.cpp -o main -I. -L. -lB -Wl,-unresolved-symbols=ignore-in-shared-libs

여전히 -rpath옵션 을 사용할 수있는 것 같습니다. 하지만 좀 더 잘 이해할 필요가 있습니다.

-Wl,-unresolved-symbols=ignore-in-shared-libs옵션을 사용할 때 가능한 함정을 아는 사람이 있습니까?

-업데이트 된 댓글 2 :

-rpath이 목적으로 사용해서는 안됩니다. 주어진 디렉토리에서 라이브러리를 강제로 찾는 것이 유용합니다. -unresolved-symbol접근 방식은 훨씬 더 보인다.

다시 한 번 감사드립니다.


당신은 이미 거기에있는 것 같습니다. 조사를 잘하셨습니다. 내가 그 뒤에있는 '이유'를 명확히하는 데 도움을 줄 수 있는지 보자.

링커가 수행하는 작업은 다음과 같습니다. 실행 파일 (위의 'main')을 연결하면 해결되지 않은 기호 (기능 및 기타 항목)가 있습니다. 해결되지 않은 기호를 해결하기 위해 다음 라이브러리 목록을 살펴 봅니다. 그 과정에서 일부 기호가 libB.so에 의해 제공된다는 것을 알게되었으므로 이제이 라이브러리에서 해당 기호가 해결되었음을 알립니다.

그러나 이러한 기호 중 일부가 실행 파일에서 아직 확인되지 않은 다른 기호를 사용한다는 사실도 발견하므로 이제 해당 기호도 해결해야합니다. libA.so에 연결하지 않으면 응용 프로그램이 불완전합니다. libA.so에 연결되면 모든 기호가 해결되고 연결이 완료됩니다.

보시다시피, 사용은 -unresolved-symbols-in-shared-libs문제를 해결하지 않습니다. 해당 기호가 런타임에 해결되도록 연기합니다. 그 이유 -rpath는 런타임에 검색 할 라이브러리를 지정하는 것입니다. 이러한 기호를 확인할 수 없으면 앱이 시작되지 않습니다.

하나 이상의 라이브러리에서 심볼을 제공하고 그중 하나에 연결하여 만족시킬 수 있기 때문에 라이브러리 종속성을 파악하는 것은 쉬운 일이 아닙니다.

여기에이 프로세스에 대한 또 다른 설명이 있습니다. 라이브러리가 링크 된 순서가 때때로 GCC에서 오류를 일으키는 이유는 무엇입니까?


직접 종속성이있는 동적 링크의 경우 다음 뒤에-Wl,--as-needed libs를 추가하는 데 사용할 수 있습니다 . -Wl,--as-needed

gcc main.c -o main -I. -L. -Wl,--as-needed -lB -lA

직접 종속성을 확인 위해 당신은 사용해야 readelf를 대신 LDD LDD는 간접 종속성을 보여주고 있기 때문이다.

$ readelf -d main | grep library
0x0000000000000001 (NEEDED)             Shared library: [libB.so]
0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

ldd는 간접 종속성도 표시합니다.

$ LD_LIBRARY_PATH=. ldd ./main
linux-vdso.so.1 (0x00007fff13717000)
libB.so => ./libB.so (0x00007fb6738ed000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb6734ea000)
libA.so => ./libA.so (0x00007fb6732e8000)
/lib64/ld-linux-x86-64.so.2 (0x00007fb673af0000)

cmake 를 사용하는 경우 직접 종속성 만 포함하도록 다음 행을 추가 할 수 있습니다.

set(CMAKE_EXE_LINKER_FLAGS    "-Wl,--as-needed ${CMAKE_EXE_LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed ${CMAKE_SHARED_LINKER_FLAGS}")

또 다른 옵션은 libtool

당신은 변경하는 경우 g++에 전화를 libtool --mode=compile g++소스 코드를 컴파일하고 다음 libtool --mode=link g++의 떨어져 응용 프로그램을 만들려면 libB, 다음 libA자동으로 연결됩니다.


This is an interesting post - I was banging my head with this as well, but I think you miss a point here..

The idea is as follows, right ?

main.cpp =(depends)=> libB.so =(depends)=> libA.so

Let's further consider that ..

  • In a.cpp (and only there) you define a class / variable, let's call it "symA"
  • In b.cpp (and only there) you define a class / variable, let's call it "symB".
  • symB uses symA
  • main.cpp uses symB

Now, libB.so and libA.so have been compiled as you described above. After that, your first option should work, i.e.:

g++ main.cpp -o main -I. -L. -lB

I guess that your problem originates from the fact that

in main.cpp you also refer to symA

Am I correct?

If you use a symbol in your code, then that symbol must be found in an .so file

The whole idea of inter-referencing shared libraries (i.e. creating APIs), is that the symbols in the deeper layers are hidden (think of peeling onions) and not used. .. i.e. don't refer to symA in your main.cpp, but only to symB instead (and let symB to refer symA only).

참고URL : https://stackoverflow.com/questions/11055569/linking-with-dynamic-library-with-dependencies

반응형