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


79

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

  • 종속성이없는 공유 라이브러리 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가 포함됩니다.

컴파일 명령 :

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

또는

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

매우 감사합니다.

-업데이트 된 댓글 :

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

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

여전히 -rpath옵션 을 사용할 수있는 것 같습니다. 그러나 나는 그것을 조금 더 잘 이해할 필요가있다.

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

-업데이트 된 댓글 2 :

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

다시 한 번 감사드립니다.


다음은 이러한 종류의 항목을 테스트하려는 사용자를위한 실행 가능한 최소 예제입니다. github.com/cirosantilli/cpp-cheat/tree/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

답변:


42

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

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

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

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

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

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


2
오래 전 일이라는 것을 알고 해결됨으로 표시하는 것을 잊었습니다. . 정말 감사합니다 귀하의 답변]
마커스

놀라운 질문과 적절한 답변에 감사드립니다! 거의 똑같은 시나리오가 있습니다. 사용자 지정 공유 개체에서 openCV 공유 개체를 래핑하려고합니다. C.so는 내 관습이고 CV.so는 일부 openCV입니다. C.so를 CV.so에 성공적으로 연결했으며 main.cpp를 C.so에 연결하고 싶지만 C.so의 개체를 사용하는 것과는 별개로 main.cpp는 CV.so에 정의 된 객체 'cv :: Mat'.이 경우 main.cpp를 실행하려면 C.so와 CV.so에 대해 링크해야합니까 ?? 누군가가 이것에 대해 밝히면 나는 그것을 좋아할 것입니다. 감사합니다! :)
Lenny Linus

2
링커가 libB.so를 생성 할 때 필요한 모든 libA.so 기호를 해결하지 않는 이유는 무엇입니까? 메인 애플리케이션은 투명해야하므로 libA에 링크 할 필요가 없습니다. 예를 들어 libB에 의해 간접적으로 보호되어야합니까?
윌슨

이것은 올바르지 않습니다. 링커는 사용자에게 불완전한 종속성 체인을 알리는 것 외에는 libA.so를 사용하지 않습니다. libA.so를 제공하지 않고 대신 -unresolved-symbols = ignore-in-shared-libs를 전달하면 동일한 실행 파일을 얻을 수 있습니다.
listerreg

21

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

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

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

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


죄송합니다. 귀하의 예제를 C ++ 대신 C 프로그램으로 만들었습니다. 따라서 gcc 컴파일러를 사용했습니다. 그러나 g ++에서도 작동합니다.
user1047271

1
정말 유용한 정보입니다. ldd 대신 readelf 사용에 대해 몰랐습니다. 매우 감사합니다.
Marcus

1

또 다른 옵션은 libtool

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


0

이것은 흥미로운 게시물입니다. 저도 이것으로 머리를 두 드렸지만 여기서 요점을 놓친 것 같습니다 ..

아이디어는 다음과 같습니다.

더 고려해 봅시다 ..

  • a.cpp (그리고 거기에만)에서 클래스 / 변수를 정의합니다. "symA"라고 부르겠습니다.
  • b.cpp (그리고 거기에서만)에서 클래스 / 변수를 정의하고 "symB"라고합시다.
  • symB는 symA를 사용합니다.
  • main.cpp는 symB를 사용합니다.

이제 libB.so와 libA.so는 위에서 설명한대로 컴파일되었습니다. 그 후에 첫 번째 옵션 작동합니다.

당신의 문제는

main.cpp에서는 symA도 참조합니다.

나 맞아?

코드에서 기호를 사용하는 경우 해당 기호는 .so 파일에서 찾아야합니다.

상호 참조 공유 라이브러리 (즉, API 생성)의 전체 아이디어는 더 깊은 레이어의 심볼이 숨겨지고 (양파 껍질을 벗기는 것을 생각해보십시오) 사용되지 않는다는 것입니다. .. 즉, main.cpp에서 symA를 참조하지 말고 대신 symB 만 참조하십시오 (그리고 symB가 symA 만 참조하도록하십시오).


1
당신은 그것을 오해했습니다. 당장 필요한 기호를 해결해야합니다. 문제는 의존성에 필요할 수있는 기호와 관련이 있습니다. 라이브러리가 사용하는 기능에 대한 구현을 제공해야하는 라이브러리 사용자와 함께 타사에서 사용할 라이브러리를 개발할 때 일반적입니다. 종속성이 전혀없는 스텁을 사용하여 개발하면 통합자가 라이브러리를 개발하여 스텁을 대체 한 다음 모든 것을 함께 연결합니다. 로더는 모든 종속성을 해결해야합니다. 그러나 컴파일 스크립트 (및 사용자)가이를 고려해야합니다.
Marcus
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.