한 배포판에서 바이너리를 빌드하여 다른 배포판에서 실행

한 배포판에서 바이너리를 빌드하여 다른 배포판에서 실행

Docker 컨테이너에 매우 간단한 명령줄 클라이언트 애플리케이션을 구축하여 고객에게 제공하고 싶습니다. 이 애플리케이션은 PEAK(이 어댑터를 만드는 회사)의 CAN-USB 어댑터를 사용합니다. PEAK는 애플리케이션이 CAN 버스에 액세스하는 데 사용하는 라이브러리(libpcanbasic)를 제공합니다.

libpcanbasic 라이브러리를 빌드하려면 어댑터의 드라이버를 설치해야 합니다. 저는 libpcanbasic.so 라이브러리를 처음 빌드하는 단계적 도커 컨테이너를 사용합니다. 그런 다음 두 번째 단계를 사용하여 업데이트된 GCC(gcc:12.1.0-bullseye)가 포함된 컨테이너를 만듭니다.

아니요, 앱을 연결하는 데 문제가 있습니다. libpcanbasic.so는 2단계 컨테이너의 일부가 아닌 libc 버전/특징에 따라 달라집니다.

# readelf -d /usr/lib/libpcanbasic.so

Dynamic section at offset 0x189b8 contains 25 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libc.musl-aarch64.so.1]
 0x000000000000000e (SONAME)             Library soname: [libpcanbasic.so]
 0x000000007ffffffd (AUXILIARY)          Auxiliary library: [visibility=hidden]
 0x000000000000000c (INIT)               0x3f38
 0x000000000000000d (FINI)               0x121f0
 0x0000000000000019 (INIT_ARRAY)         0x28998
 0x000000000000001b (INIT_ARRAYSZ)       16 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x289a8
 0x000000000000001c (FINI_ARRAYSZ)       16 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x190
 0x0000000000000005 (STRTAB)             0x1638
 0x0000000000000006 (SYMTAB)             0x558
 0x000000000000000a (STRSZ)              2719 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000003 (PLTGOT)             0x28b88
 0x0000000000000002 (PLTRELSZ)           3096 (bytes)
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000017 (JMPREL)             0x3320
 0x0000000000000007 (RELA)               0x20d8
 0x0000000000000008 (RELASZ)             4680 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x0000000000000018 (BIND_NOW)           
 0x000000006ffffffb (FLAGS_1)            Flags: NOW
 0x000000006ffffff9 (RELACOUNT)          185
 0x0000000000000000 (NULL)               0x0

libc 파일(libc.musl-aarch64.so.1)을 /lib두 번째 단계 컨테이너에 복사하고 연결하면 됩니다.

# readelf -d ./build/client/bootloader_client 

    Dynamic section at offset 0x14da8 contains 29 entries:
      Tag        Type                         Name/Value
     0x0000000000000001 (NEEDED)             Shared library: [libpcanbasic.so]
     0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
     0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
     0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
     0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
     0x000000000000000c (INIT)               0x402d98
     0x000000000000000d (FINI)               0x40e670
     0x0000000000000019 (INIT_ARRAY)         0x424d78
     0x000000000000001b (INIT_ARRAYSZ)       16 (bytes)
     0x000000000000001a (FINI_ARRAY)         0x424d88
     0x000000000000001c (FINI_ARRAYSZ)       8 (bytes)
     0x0000000000000004 (HASH)               0x400278
     0x000000006ffffef5 (GNU_HASH)           0x4005d0
     0x0000000000000005 (STRTAB)             0x4010d0
     0x0000000000000006 (SYMTAB)             0x400620
     0x000000000000000a (STRSZ)              4274 (bytes)
     0x000000000000000b (SYMENT)             24 (bytes)
     0x0000000000000015 (DEBUG)              0x0
     0x0000000000000003 (PLTGOT)             0x424fe8
     0x0000000000000002 (PLTRELSZ)           2448 (bytes)
     0x0000000000000014 (PLTREL)             RELA
     0x0000000000000017 (JMPREL)             0x402408
     0x0000000000000007 (RELA)               0x402318
     0x0000000000000008 (RELASZ)             240 (bytes)
     0x0000000000000009 (RELAENT)            24 (bytes)
     0x000000006ffffffe (VERNEED)            0x402268
     0x000000006fffffff (VERNEEDNUM)         3
     0x000000006ffffff0 (VERSYM)             0x402182
     0x0000000000000000 (NULL)               0x0            

하지만 생성된 바이너리를 다른 곳에서 실행하려고 하면 문제가 발생할 것 같습니다.

왜 애플리케이션과 공유 객체(libpcanbasic.so)가 단지 의존하지 않습니까 libc.so? 왜 매우 구체적인 버전인가요? 이것이 바뀔 수 있습니까? 그리고 클라이언트에게 바이너리를 제공하려는 경우 모범 사례는 무엇입니까?

감사합니다, 토스턴

답변1

libc.so귀하의 라이브러리는 다음을 사용하고 있기 때문에 "그냥 의존"하는 것으로 끝나지 않습니다.muslerlibc(첫 번째 단계에서는 Alpine 기반 컨테이너 이미지를 사용하는 것 같습니다.) 귀하의 신청서는 어느 libc.so누구 에게도 의존하지 않지만 ,libc.so.6GNU C 라이브러리(Debian을 기반으로 구축되었으며 기본적으로 GNU C 라이브러리를 사용합니다).

컨테이너 빌드에 익숙하기 때문에 고객에게 바이너리를 제공하는 가장 좋은 방법은 지원하려는 대상에 해당하는 컨테이너 이미지를 사용하여 바이너리를 빌드하는 것입니다. 내가 아는 한 귀하의 라이브러리에는 특정 종속성이 없으므로 GNU C 라이브러리를 기반으로 하는 이전 배포판을 사용하여 빌드하여 유지 관리 부담을 단순화할 수 있습니다(동일한 라이브러리 버전 라이브러리를 사용하는 모든 배포판에서 작동하는 라이브러리를 빌드하세요) 나중에 musl 기반 배포판에 사용), musl 기반 대상을 지원하려면 musl 기반 배포판을 사용할 수 있습니다.

다단계 빌드를 진행하는 경우 최소한 모든 단계가 동일한 이미지(또는 호환 가능한 이미지)를 기반으로 하는지 확인해야 합니다.

관련 정보