정적/동적 라이브러리의 이름을 결정합니다.

정적/동적 라이브러리의 이름을 결정합니다.

저는 Unix/Linux C 라이브러리(예 : ) 를 사용하는 타사 C 코드 조각으로 작업하는 경우가 많습니다 #include <glib.h>. 예 를 #include <net/if.h>들어 특정 라이브러리 파일 이름이나 pkg-config 이름을 알아야 합니다 . "2.0", "1"의 헤더 파일이 달라서 추측할 수 없습니다.-lglib-2.0-lbluetoothpkg-config --libs dbus-1

API/라이브러리가 소유한 라이브러리 파일의 정확한 이름을 어떻게 찾을 수 있나요? 위의 예를 사용하면 #include <glib.h>라이브러리 파일의 이름을 어떻게 찾을 수 있습니까 -lglib-2.0? 실망스럽게도 Glib/dbus/all에 대한 온라인 참조에는 "라이브러리 파일 이름이 glib-2.0입니다"라고만 나와 있지 않습니다.

이를 파악하는 데 사용할 수 있는 터미널 명령이 있습니까? 이를 알아내는 데 사용할 수 있는 유틸리티가 있습니까? 온라인 API/라이브러리 참조는 이것을 찾는 데 정말 좋지 않습니다.

위치 를 찾고 싶다면 hci.h쉽게 찾을 수 있습니다 locate hci.h. 라이브러리 이름을 찾는 터미널 명령과 같은 것이 있습니까?

답변1

특정 기능을 사용하는 데 어떤 라이브러리가 필요한지 알 수 있는 일반적인 방법은 없습니다. 이 라이브러리에 대한 설명서를 확인해야 합니다. 잘 작성된 튜토리얼이나 API 참조는 이것이 무엇인지 알려줄 것입니다.

적어도 도서관이 무엇인지는 이해할 수 있습니다.필수: 헤더 파일이 포함된 라이브러리 패키지와 동일합니다. 헤더 파일이 포함된 패키지를 확인하는 방법은 배포판(예: dpkg -S /usr/include/glib-2.0/glib.hDebian/Ubuntu/Mint/..., rpm -qf /usr/include/glib-2.0/glib.hRHEL/CentOS/Fedora/... 등) 에 따라 다릅니다. 라이브러리 패키지를 알고 나면 해당 내용을 나열하여 .so포함된 파일을 찾습니다.

dpkg -L libglib2.0-dev | grep '\.so$'
rpm -qlf /usr/include/glib-2.0/glib.h | grep '\.so$'

Glib에는 여러 .so파일이 있으며 특정 기능에 어떤 파일이 필요한지 자동으로 알 수 있는 방법이 없습니다(여러 파일이 있을 수 있음).

라이브러리에서 이를 사용하는 경우 pkg-config헤더 및 라이브러리 경로를 하드코딩하는 대신 이를 사용해야 합니다. 그러나 모든 도서관이 이를 사용하는 것은 아닙니다. 배포판의 라이브러리 패키지는 해당 pkg-config패키지(예 dpkg -s libglib2.0-dev |grep '^Depends:.*pkg-config': )에 종속되어야 하기 때문에 일반적으로 알 수 있습니다.

문서가 정말 형편없으면 라이브러리에서 정의한 기호를 나열해 보세요.

nm -D /usr/lib/x86_64-linux-gnu/libgio-2.0.so |awk '$2=="T" {print $3}'

다른 라이브러리가 필요한지 알려주지 않으므로 이는 완벽한 방법이 아닙니다.

답변2

이러한 #include명령어는 C 전처리기에 의해 확장됩니다. 검색 경로는 컴파일러(예: -I<dir>플래그)에 의해 제어됩니다. 생성된 개체 파일에 기호를 제공합니다.

그런 다음 링커는 규칙을 사용하여 이러한 기호를 아카이브/객체 파일에 매핑합니다. 유사한 플래그가 주어지면 -l<namespec>링커는 라이브러리 경로 lib<namespec>.a또는 의 디렉터리에서 검색합니다 lib<namespec>.so. 링커는 생성된 바이너리에 이러한 파일 이름을 포함하고 동적 링커는 런타임에 이러한 파일 이름을 사용하여 기호를 실제 구현으로 해석합니다.

검색 디렉토리를 사용하여 컴파일러 링커를 찾을 수 있습니다 ld --verbose | grep SEARCH_DIR. 예를 들어 다음은 링커가 라이브러리 이름을 파일에 매핑하는 방법을 대략적으로 시뮬레이션합니다 .so.

$ libname=glib-2.0; ld --verbose |  grep SEARCH_DIR |  tr -s ' ;' '\n' |  sed 's/SEARCH_DIR("=\?\(.*\)")/\1/g' |  xargs -I{} find {} -maxdepth 1 2>/dev/null | grep lib${libname}.so
/usr/lib/libglib-2.0.so.0.7000.0
/usr/lib/libglib-2.0.so
/usr/lib/libglib-2.0.so.0

(이것들은 모두 동일한 파일에 대한 심볼릭 링크입니다.)

패키지 관리자에서 이 파일을 제공하는 패키지를 찾을 수 있습니다 yum. 예를 들면 다음과 같습니다.

$ yum whatprovides /usr/lib64/libglib-2.0.so.0

glib2-2.68.1-1.fc34.x86_64 : A library of handy utility functions
Repo        : fedora
Matched from:
Filename    : /usr/lib64/libglib-2.0.so.0

glib2-2.68.4-1.fc34.x86_64 : A library of handy utility functions
Repo        : @System
Matched from:
Filename    : /usr/lib64/libglib-2.0.so.0

glib2-2.68.4-1.fc34.x86_64 : A library of handy utility functions
Repo        : updates
Matched from:
Filename    : /usr/lib64/libglib-2.0.so.0

다음 명령을 사용하여 기호를 볼 수 있습니다 nm.

$ nm -D --defined-only /usr/lib/libglib-2.0.so.0
0000000000070000 T g_access
000000000001d600 T g_allocator_free
000000000001d5f0 T g_allocator_new
0000000000022810 T g_array_append_vals
000000000001e3a0 T g_array_binary_search
...

링커 규칙은 에 문서화되어 있습니다 man ld.

마지막으로 귀하의 질문에 답변해 드리겠습니다. 이러한 메커니즘은 실제 구현에서 헤더를 분리하도록 설계되었으므로 설계상 헤더를 개체/아카이브에 매핑하는 보편적인 방법은 없습니다. 결국에는 .so기호를 구현하는 파일을 찾아야 합니다 #include. 다른 답변에서 말했듯이 이것은 일시적입니다.

그러나 패키지 관리자는 일반적으로 헤더 파일을 제공하는 패키지이고 <package>-devel해당 패키지는 <package>공유 객체를 제공하므로 많은 도움이 됩니다. 예를 들어, yum이를 사용하여 개발 패키지를 찾을 수 있습니다.

$ yum provides '*/glib.h'

glib-devel-1:1.2.10-62.fc34.i686 : Libraries and header files for glib development
Repo        : fedora
Matched from:
Filename    : /usr/include/glib-1.2/glib.h

glib-devel-1:1.2.10-62.fc34.x86_64 : Libraries and header files for glib development
Repo        : fedora
Matched from:
Filename    : /usr/include/glib-1.2/glib.h

glib2-devel-2.68.1-1.fc34.i686 : A library of handy utility functions
Repo        : fedora
Matched from:
Filename    : /usr/include/glib-2.0/glib.h

...

glib2-devel패키지에 헤더 파일이 제공되는 것을 볼 수 있습니다 . 따라서 glib2패키지는 해당 .so파일을 제공하며 해당 파일 이름에서 사용할 플래그가 무엇인지 알 수 있습니다 -l.

$ repoquery -l glib2 | grep '.so'

/usr/lib/libgio-2.0.so.0
/usr/lib/libgio-2.0.so.0.6800.4
/usr/lib/libglib-2.0.so.0
/usr/lib/libglib-2.0.so.0.6800.4
...

따라서 를 고려하면 glib.h최소한 을 사용해야 한다는 것을 알 수 있습니다 -lglib-2.0.

관련 정보