단일 호스트의 여러 glibc 라이브러리


171

단일 호스트의 여러 glibc 라이브러리

내 Linux (SLES-8) 서버에는 현재 glibc-2.2.5-235가 있지만이 버전에서 작동하지 않으며 glibc-2.3.3이 필요한 프로그램이 있습니다.

동일한 호스트에 여러 개의 glibcs를 설치할 수 있습니까?

이것은 이전 glibc에서 프로그램을 실행할 때 발생하는 오류입니다.

./myapp: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by ./myapp)
./myapp: /lib/i686/libpthread.so.0: version `GLIBC_2.3.2' not found (required by ./myapp)
./myapp: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by ./libxerces-c.so.27)
./myapp: /lib/ld-linux.so.2: version `GLIBC_2.3' not found (required by ./libstdc++.so.6)
./myapp: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by ./libstdc++.so.6)

그래서 newglibc라는 새 디렉토리를 만들고 다음 파일을 복사했습니다.

libpthread.so.0
libm.so.6
libc.so.6
ld-2.3.3.so
ld-linux.so.2 -> ld-2.3.3.so

export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH

그러나 오류가 발생합니다.

./myapp: /lib/ld-linux.so.2: version `GLIBC_PRIVATE' not found (required by ./newglibc/libpthread.so.0)
./myapp: /lib/ld-linux.so.2: version `GLIBC_2.3' not found (required by libstdc++.so.6)
./myapp: /lib/ld-linux.so.2: version `GLIBC_PRIVATE' not found (required by ./newglibc/libm.so.6)
./myapp: /lib/ld-linux.so.2: version `GLIBC_2.3' not found (required by ./newglibc/libc.so.6)
./myapp: /lib/ld-linux.so.2: version `GLIBC_PRIVATE' not found (required by ./newglibc/libc.so.6)

그래서 그들은 여전히 ​​/ lib에 연결되어 있고 내가 놓은 곳에서 픽업하지 않는 것 같습니다.

감사


1
SLES-11 서버와 동일한 문제입니다. 업데이트 할 수 없으며 최근 항목이 필요합니다. 오 마이 ...
UmNyobe

FWIW는 export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH 않았다 나를 위해 문제를 해결! 확실히 모든 사람에게 적용되지는 않지만 작동하면 쉽게 해결할 수 있습니다! 감사! :)
rinogo 2016 년

답변:


229

동일한 시스템에서 여러 버전의 glibc를 사용할 수 있습니다 (매일 그렇게합니다).

그러나 glibc는 모두 일치해야하는 많은 조각 (200 개 이상의 공유 라이브러리)으로 구성되어 있습니다. 조각 중 하나는 ld-linux.so.2이며 libc.so.6와 일치 해야합니다. 그렇지 않으면보고있는 오류가 표시됩니다.

ld-linux.so.2의 절대 경로는 링크 타임에 실행 파일에 하드 코딩되어 있으며 링크가 완료된 후에는 쉽게 변경할 수 없습니다.

새로운 glibc와 호환되는 실행 파일을 빌드하려면 다음과 같이하십시오 :

g++ main.o -o myapp ... \
   -Wl,--rpath=/path/to/newglibc \
   -Wl,--dynamic-linker=/path/to/newglibc/ld-linux.so.2

-rpath링커 옵션에서 라이브러리 런타임 로더 검색 할 것입니다 /path/to/newglibc(당신은 설정할 필요가 없습니다 것입니다, 그래서 LD_LIBRARY_PATH그것을 실행하기 전에)를, 그리고 -dynamic-linker해결하려면 옵션 것이다 "빵"경로 ld-linux.so.2응용 프로그램에.

myapp응용 프로그램을 다시 연결할 수없는 경우 (예 : 타사 바이너리이므로) 모두 손실되지는 않지만 까다로워집니다. 한 가지 해결책은 적절한 chroot환경 을 설정하는 것입니다. 또 다른 가능성은 rtldi이진 편집기 를 사용 하는 것 입니다.


3
하는 것으로는 -Wl,--dynamic-linker=fileELF 실행 파일 용으로 컴파일 할 경우에만 작동합니다 - ( ''두 소요). 점검/sbin/ldconfig -p | grep ld
Tom

49
이제 편리한 유틸리티 patchelf( nixos.org/patchelf.html )를 사용하여 이미 컴파일 된 ELF의 rpath 및 인터프리터를 수정할 수 있습니다.
Michael Pankov

10
사용하여 새의 glibc의 경로를 지정하는 것을 언급 그것의 가치 -Wl,--rpath보다는하는 것이 LD_LIBRARY_PATH편리가 아닌 다른 이유로 중요 할 수는 : 프로그램 출시 자식 프로세스 경우의 가치 LD_LIBRARY_PATH가 있다면 일반적으로 그들에 의해 상속됩니다은, 또한 사용에 컴파일되지 최신 glibc (예 :와 같은 주식 바이너리 인 경우 bash)는 시작되지 않습니다.
HighCommander4 4

13
다른 옵션은 새로운 ld.so를 직접 실행하여 바이너리 프로그램을 매개 변수로 전달하는 것입니다. 이것은 프로그램을 다시 컴파일 할 필요없이 사용 된 ld.so를 효과적으로 대체합니다 :/path/to/newglibc/ld-linux.so.2 --library-path /path/tonewglibc/lib64:/path/to/newglibc/usr/lib64 /path/to/myapp
maximk


67

이 질문은 오래되었고 다른 답변은 오래되었습니다. "고용 된 러시아어"의 대답은 매우 유익하고 유익하지만 소스 코드가있는 경우에만 작동합니다. 그렇지 않으면 대안이 매우 까다 롭습니다. 다행히 오늘날 우리는 patchelf를 사용하여 (그의 답글 중 하나에서 언급 한 것처럼)이 문제에 대한 간단한 해결책을 가지고 있습니다 . 당신이해야 할 일은 :

$ ./patchelf --set-interpreter /path/to/newglibc/ld-linux.so.2 --set-rpath /path/to/newglibc/ myapp

그리고 나서 파일을 실행할 수 있습니다.

$ ./myapp

chroot고맙게도 바이너리를 수동으로 편집 할 필요가 없습니다 . 그러나 바이너리 파일을 수정하기 때문에 수행중인 작업이 확실하지 않은 경우 패치하기 전에 바이너리를 백업해야합니다. 패치 한 후에는 기존 경로를 인터프리터 / rpath로 복원 할 수 없습니다. 작동하지 않는 경우 실제로 작동 할 경로를 찾을 때까지 계속 패치해야합니다. 음, 시행 착오 과정 일 필요는 없습니다. 예를 들어, OP의 예에서 그는 필요 GLIBC_2.3하므로 다음을 사용하여 해당 버전을 제공하는 lib를 쉽게 찾을 수 있습니다 strings.

$ strings /lib/i686/libc.so.6 | grep GLIBC_2.3
$ strings /path/to/newglib/libc.so.6 | grep GLIBC_2.3

이론적으로 첫 번째 grep은 시스템 libc에 원하는 버전이 없기 때문에 비어있을 것이고, 두 번째 grep은 버전 myapp이 사용 중이므로 GLIBC_2.3을 출력해야 하므로 patchelf해당 경로를 사용하여 바이너리를 사용할 수 있습니다 .

리눅스에서 바이너리를 실행하려고 할 때 바이너리는 링커를로드하려고 시도한 다음 라이브러리를로드하려고하며 경로 및 / 또는 올바른 위치에 있어야합니다. 링커에 문제가 있고 바이너리가 찾는 경로를 찾으려면 다음 명령을 사용하십시오.

$ readelf -l myapp | grep interpreter
  [Requesting program interpreter: /lib/ld-linux.so.2]                                                                                                                                                                                   

libs에 문제가있는 경우 사용중인 lib를 제공하는 명령은 다음과 같습니다.

$ readelf -d myapp | grep Shared
$ ldd myapp 

바이너리에 필요한 라이브러리가 나열되지만 OP의 경우와 같이 이미 오류가 발생하기 때문에 문제가있는 라이브러리를 이미 알고있을 것입니다.

"patchelf"는이 두 가지 문제와 관련된 프로그램을 실행하려고 할 때 발생할 수있는 여러 가지 문제에 적용됩니다. 예를 들어, 당신이 얻는다면 : here 설명하는 것처럼 ELF file OS ABI invalid새 로더 ( --set-interpreter명령 의 일부)를 설정하여 수정 될 수 있습니다 . 또 다른 예는 여기에 예시 된 것처럼 파일이 있고 실행 가능한 파일을 실행할 때 발생하는 문제입니다 . 이 특정 경우 OP에는 로더에 대한 링크가 누락되었지만 루트 액세스 권한이 없으며 링크를 만들 수 없습니다. 새로운 통역사를 설정하면 문제가 해결됩니다.No such file or directory

통찰력과 해결책에 대해 러시아어와 Michael Pankov를 고용해 주셔서 감사합니다!


1
가장 도움이되었습니다! 나는 tensorflow를 위해 새로운 glibc를 사용하기 위해 파이썬 바이너리를 패치했다
faizan

이것은 깔끔한 해결책 patchelf이지만 이전에 알지 못했지만 "이진을 편집 할 필요가 없습니다"라는 문구가 약간 잘못 될 수 있습니다 (실제로 바이너리를 편집하고 있기 때문에).
Larsks

거기에 고정되어 있습니다. ;)
msb

정말 유용한 유틸리티! 감사합니다! 몇 시간 동안 수동으로 종속성을 해결 한 다음 관리자 권한없이 크롬을 로컬로 설치하기 위해 모든 것을 패치 한 후에 세그먼트 오류 만 얻을 수 있었지만 ...
G. Bergeron

@fgiraldeau 칭찬에 감사드립니다. :) 그러나 2009 년에 질문을하고, 대답하고, 받아 들였다면, 누군가 대답을 받아들이 기 전에 8 년을 기다리지 않을 것입니다. heheh; D
msb 2018 년

20

LD_PRELOAD를 사용하십시오 : 라이브러리를 man lib 디렉토리 외부에 놓고 다음을 실행하십시오.

LD_PRELOAD='mylibc.so anotherlib.so' program

참조 : Wikipedia article


1
이 복잡한 메이크위한 좋은 해결 방법이 될 것이라고 생각하지만, 나를 위해 작동하지 않았다
갈락 티카

그의 유용한 특히 더 소스 binary.thanks 없습니다
코더

2
음 ... 나는 틀렸다, 소스 컴파일 및 링크하는 동안 / path / to / new / lib / frist에 ld-linux.so를 rpath 해야하는 것처럼 보인다
coder

1
ld-#. ##. so (시스템 glibc lib에서)가 libc.so. # (대체 glibc lib에서)와 동일한 glibc 버전이 아닌 경우 작동하지 않습니다.
Andy

12

우선, 동적으로 링크 된 각 프로그램의 가장 중요한 종속성은 링커입니다. 따라서 라이브러리는 링커 버전과 일치해야합니다.

간단한 exaple을 보자 : 나는 어떤 프로그램을 실행하는 새로운 우분투 시스템을 가지고있다 (내 경우에는 D 컴파일러-ldc2). 이전 CentOS에서 실행하고 싶지만 이전 glibc 라이브러리로 인해 불가능합니다. 알았어

ldc2-1.5.0-linux-x86_64/bin/ldc2: /lib64/libc.so.6: version `GLIBC_2.15' not found (required by ldc2-1.5.0-linux-x86_64/bin/ldc2)
ldc2-1.5.0-linux-x86_64/bin/ldc2: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by ldc2-1.5.0-linux-x86_64/bin/ldc2)

우분투에서 센토로 모든 의존성을 복사해야합니다. 올바른 방법은 다음과 같습니다.

먼저 모든 의존성을 확인하자 :

ldd ldc2-1.5.0-linux-x86_64/bin/ldc2 
    linux-vdso.so.1 =>  (0x00007ffebad3f000)
    librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f965f597000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f965f378000)
    libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f965f15b000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f965ef57000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f965ec01000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f965e9ea000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f965e60a000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f965f79f000)

linux-vdso.so.1은 실제 라이브러리가 아니므로 신경 쓸 필요가 없습니다.

/lib64/ld-linux-x86-64.so.2는 리눅스가 실행 파일을 모든 동적 라이브러리와 연결하는 데 사용되는 링커입니다.

나머지 파일은 실제 라이브러리이며 링커와 함께 모두 centos 어딘가에 복사해야합니다.

모든 라이브러리와 링커가 "/ mylibs"디렉토리에 있다고 가정합니다.

ld-linux-x86-64.so.2는 이미 말했듯이 링커입니다. 동적 라이브러리는 아니지만 정적 실행 파일입니다. 당신은 그것을 실행할 수 있으며 --library-path와 같은 매개 변수가 있음을 알 수 있습니다 (돌아가겠습니다).

리눅스에서 동적으로 링크 된 프로그램은 이름만으로 점심을 먹을 수 있습니다.

/bin/ldc2

Linux는 이러한 프로그램을 RAM에로드하고 어떤 링커가 설정되어 있는지 확인합니다. 일반적으로 64 비트 시스템에서는 /lib64/ld-linux-x86-64.so.2입니다 (파일 시스템에서는 실제 실행 파일에 대한 심볼릭 링크 임). 그런 다음 리눅스는 링커를 실행하고 동적 라이브러리를로드합니다.

이것을 조금 변경하고 그러한 트릭을 수행 할 수도 있습니다.

/mylibs/ld-linux-x86-64.so.2 /bin/ldc2

리눅스가 특정 링커를 사용하도록하는 방법입니다.

이제 앞서 언급 한 매개 변수 --library-path로 돌아갈 수 있습니다.

/mylibs/ld-linux-x86-64.so.2 --library-path /mylibs /bin/ldc2

ldc2를 실행하고 / mylibs에서 동적 라이브러리를로드합니다.

선택한 (시스템 기본값 아님) 라이브러리를 사용하여 실행 파일을 호출하는 방법입니다.


RH7에서 프로그램을 컴파일하여 RH6에서 실행해야합니다. 새로운 실행 파일을 작성하거나 patchelf를 사용하고 싶지 않으므로 이것이 훌륭한 대안입니다.
Mark Rajcok

9

설정 1 : 전용 GCC없이 자신의 glibc를 컴파일하여 사용하십시오

이 설정은 전체 GCC 툴체인을 다시 컴파일하지 않고 glibc로 빠르게 작동 할 수 있습니다.

그것뿐만 호스트 C 런타임 객체는 사용하지만 이는 신뢰성없는 crt1.o, crti.o그리고 crtn.oglibc에 의해 제공. : 이것은에서 언급 https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location 일이 멋진 추락하면 나는 놀라지 않을 것이다, 그래서 그 객체가, glibc는가에 의존 초기 설정을 놀랍도록 미묘한 방법.

보다 안정적인 설정은 아래의 설정 2를 참조하십시오.

glibc를 빌드하고 로컬로 설치하십시오.

export glibc_install="$(pwd)/glibc/build/install"

git clone git://sourceware.org/git/glibc.git
cd glibc
git checkout glibc-2.28
mkdir build
cd build
../configure --prefix "$glibc_install"
make -j `nproc`
make install -j `nproc`

설정 1 : 빌드 확인

test_glibc.c

#define _GNU_SOURCE
#include <assert.h>
#include <gnu/libc-version.h>
#include <stdatomic.h>
#include <stdio.h>
#include <threads.h>

atomic_int acnt;
int cnt;

int f(void* thr_data) {
    for(int n = 0; n < 1000; ++n) {
        ++cnt;
        ++acnt;
    }
    return 0;
}

int main(int argc, char **argv) {
    /* Basic library version check. */
    printf("gnu_get_libc_version() = %s\n", gnu_get_libc_version());

    /* Exercise thrd_create from -pthread,
     * which is not present in glibc 2.27 in Ubuntu 18.04.
     * /programming/56810/how-do-i-start-threads-in-plain-c/52453291#52453291 */
    thrd_t thr[10];
    for(int n = 0; n < 10; ++n)
        thrd_create(&thr[n], f, NULL);
    for(int n = 0; n < 10; ++n)
        thrd_join(thr[n], NULL);
    printf("The atomic counter is %u\n", acnt);
    printf("The non-atomic counter is %u\n", cnt);
}

다음과 test_glibc.sh같이 컴파일하고 실행하십시오 .

#!/usr/bin/env bash
set -eux
gcc \
  -L "${glibc_install}/lib" \
  -I "${glibc_install}/include" \
  -Wl,--rpath="${glibc_install}/lib" \
  -Wl,--dynamic-linker="${glibc_install}/lib/ld-linux-x86-64.so.2" \
  -std=c11 \
  -o test_glibc.out \
  -v \
  test_glibc.c \
  -pthread \
;
ldd ./test_glibc.out
./test_glibc.out

프로그램은 다음을 예상합니다.

gnu_get_libc_version() = 2.28
The atomic counter is 10000
The non-atomic counter is 8674

명령에서 적응 https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location 하지만 --sysroot그것은 실패했다 :

cannot find /home/ciro/glibc/build/install/lib/libc.so.6 inside /home/ciro/glibc/build/install

그래서 제거했습니다.

ldd출력 ldd은 방금 빌드 한 및 라이브러리가 실제로 예상대로 사용되고 있음을 확인합니다 .

+ ldd test_glibc.out
        linux-vdso.so.1 (0x00007ffe4bfd3000)
        libpthread.so.0 => /home/ciro/glibc/build/install/lib/libpthread.so.0 (0x00007fc12ed92000)
        libc.so.6 => /home/ciro/glibc/build/install/lib/libc.so.6 (0x00007fc12e9dc000)
        /home/ciro/glibc/build/install/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007fc12f1b3000)

gcc이전에 언급,하지만 난 그것을 해결할 방법을 알고하지 않는 나쁜 나의 호스트 런타임 개체가 사용 된 것을 컴파일 디버그 출력 쇼, 예를 들어, 그것은 포함 :

COLLECT_GCC_OPTIONS=/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crt1.o

설정 1 : glibc 수정

이제 glibc를 다음과 같이 수정하자 :

diff --git a/nptl/thrd_create.c b/nptl/thrd_create.c
index 113ba0d93e..b00f088abb 100644
--- a/nptl/thrd_create.c
+++ b/nptl/thrd_create.c
@@ -16,11 +16,14 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */

+#include <stdio.h>
+
 #include "thrd_priv.h"

 int
 thrd_create (thrd_t *thr, thrd_start_t func, void *arg)
 {
+  puts("hacked");
   _Static_assert (sizeof (thr) == sizeof (pthread_t),
                   "sizeof (thr) != sizeof (pthread_t)");

그런 다음 glibc를 다시 컴파일하고 다시 설치하고 프로그램을 다시 컴파일하고 다시 실행하십시오.

cd glibc/build
make -j `nproc`
make -j `nproc` install
./test_glibc.sh

hacked예상대로 몇 번 인쇄 된 것을 볼 수 있습니다.

이것은 우리가 실제로 컴파일 한 glibc를 호스트가 아닌 glibc를 사용했음을 확인합니다.

우분투 18.04에서 테스트되었습니다.

설정 2 : crosstool-NG 초기 설정

이 설정 1의 대안이며, 그것은 내가 지금까지 달성 한 가장 올바른 설정입니다 : 모든 것을 내가 C 런타임과 같은 개체를 포함하여 관찰 할 수있는만큼 지금까지 올바른지 crt1.o, crti.o그리고 crtn.o.

이 설정에서는 원하는 glibc를 사용하는 완전한 전용 GCC 툴체인을 컴파일합니다.

이 방법의 유일한 단점은 빌드 시간이 더 오래 걸린다는 것입니다. 그러나 나는 더 적은 것을 가진 생산 체제의 위험을 감수하지 않을 것입니다.

crosstool-NG 는 GCC, glibc 및 binutils를 포함하여 소스의 모든 것을 다운로드하고 컴파일하는 스크립트 세트입니다.

예. GCC 빌드 시스템이 너무 나빠서 별도의 프로젝트가 필요합니다.

crosstool-NG는 여분의 -Wl플래그 없이 실행 파일을 빌드하는 것을 지원하지 않기 때문에 완벽 하지 않습니다 . GCC 자체를 빌드 한 이후로 이상하게 느껴집니다. 그러나 모든 것이 작동하는 것처럼 보이므로 이는 불편한 일입니다.

crosstool-NG를 가져 와서 구성하고 빌드하십시오.

git clone https://github.com/crosstool-ng/crosstool-ng
cd crosstool-ng
git checkout a6580b8e8b55345a5a342b5bd96e42c83e640ac5
export CT_PREFIX="$(pwd)/.build/install"
export PATH="/usr/lib/ccache:${PATH}"
./bootstrap
./configure --enable-local
make -j `nproc`
./ct-ng x86_64-unknown-linux-gnu
./ct-ng menuconfig
env -u LD_LIBRARY_PATH time ./ct-ng build CT_JOBS=`nproc`

빌드에는 약 30 분에서 2 시간이 걸립니다.

내가 볼 수있는 유일한 필수 구성 옵션은 올바른 커널 헤더를 사용하기 위해 호스트 커널 버전과 일치시키는 것입니다. 다음을 사용하여 호스트 커널 버전을 찾으십시오.

uname -a

그것은 나를 보여줍니다 :

4.15.0-34-generic

그래서 menuconfig나는 :

  • Operating System
    • Version of linux

그래서 나는 선택합니다 :

4.14.71

첫 번째 동일하거나 이전 버전입니다. 커널은 이전 버전과 호환되므로 이전 버전이어야합니다.

설정 2 : 옵션 구성

.config우리는 생성하는 것이 ./ct-ng x86_64-unknown-linux-gnu있다 :

CT_GLIBC_V_2_27=y

이를 변경하려면 다음을 menuconfig수행하십시오.

  • C-library
  • Version of glibc

를 저장하고 .config빌드를 계속하십시오.

또는 최신 git의 glibc를 사용하기 위해 자신의 glibc 소스를 사용하려면 다음 과 같이 진행 하십시오 .

  • Paths and misc options
    • Try features marked as EXPERIMENTAL: true로 설정
  • C-library
    • Source of glibc
      • Custom location: 예라고
      • Custom location
        • Custom source location: glibc 소스를 포함하는 디렉토리를 가리 킵니다.

glibc는 다음과 같이 복제되었습니다.

git clone git://sourceware.org/git/glibc.git
cd glibc
git checkout glibc-2.28

설정 2 : 테스트

원하는 툴체인을 구축했으면 다음을 사용하여 테스트하십시오.

#!/usr/bin/env bash
set -eux
install_dir="${CT_PREFIX}/x86_64-unknown-linux-gnu"
PATH="${PATH}:${install_dir}/bin" \
  x86_64-unknown-linux-gnu-gcc \
  -Wl,--dynamic-linker="${install_dir}/x86_64-unknown-linux-gnu/sysroot/lib/ld-linux-x86-64.so.2" \
  -Wl,--rpath="${install_dir}/x86_64-unknown-linux-gnu/sysroot/lib" \
  -v \
  -o test_glibc.out \
  test_glibc.c \
  -pthread \
;
ldd test_glibc.out
./test_glibc.out

올바른 런타임 객체가 사용되었다는 점을 제외하고는 모든 것이 설치 1에서와 같이 작동하는 것 같습니다.

COLLECT_GCC_OPTIONS=/home/ciro/crosstool-ng/.build/install/x86_64-unknown-linux-gnu/bin/../x86_64-unknown-linux-gnu/sysroot/usr/lib/../lib64/crt1.o

설정 2 : 효율적인 glibc 재 컴파일 시도 실패

아래 설명과 같이 crosstool-NG에서는 불가능한 것 같습니다.

방금 재건한다면;

env -u LD_LIBRARY_PATH time ./ct-ng build CT_JOBS=`nproc`

그런 다음 사용자 정의 glibc 소스 위치에 대한 변경 사항이 고려되지만 처음부터 모든 것을 빌드하므로 반복 개발에 사용할 수 없습니다.

우리가 할 경우 :

./ct-ng list-steps

빌드 단계에 대한 훌륭한 개요를 제공합니다.

Available build steps, in order:
  - companion_tools_for_build
  - companion_libs_for_build
  - binutils_for_build
  - companion_tools_for_host
  - companion_libs_for_host
  - binutils_for_host
  - cc_core_pass_1
  - kernel_headers
  - libc_start_files
  - cc_core_pass_2
  - libc
  - cc_for_build
  - cc_for_host
  - libc_post_cc
  - companion_libs_for_target
  - binutils_for_target
  - debug
  - test_suite
  - finish
Use "<step>" as action to execute only that step.
Use "+<step>" as action to execute up to that step.
Use "<step>+" as action to execute from that step onward.

따라서 우리는 glibc 단계가 여러 GCC 단계와 얽혀 있으며, 가장 주목할만한 것은 libc_start_files이전 단계이며 cc_core_pass_2, 이는 아마도 가장 비싼 단계 일 것입니다 cc_core_pass_1.

한 단계 만 만들려면 먼저 .config초기 빌드에 대해 "중간 단계 저장"옵션을 설정해야합니다 .

  • Paths and misc options
    • Debug crosstool-NG
      • Save intermediate steps

그리고 당신은 시도 할 수 있습니다 :

env -u LD_LIBRARY_PATH time ./ct-ng libc+ -j`nproc`

그러나 불행히도 https://github.com/crosstool-ng/crosstool-ng/issues/1033#issuecomment-424877536에+ 언급 된대로 필요합니다.

그러나 중간 단계에서 다시 시작하면 설치 디렉토리가 해당 단계 동안의 상태로 재설정됩니다. 즉, libc를 다시 빌드 할 수 있지만이 libc로 빌드 된 최종 컴파일러는 없습니다 (따라서 libstdc ++와 같은 컴파일러 라이브러리도 없음).

기본적으로 여전히 재 구축이 너무 느려 개발에 적합하지 않으며 crosstool-NG를 패치하지 않고 이것을 극복하는 방법을 알지 못합니다.

또한 libc단계 부터 시작하여에서 소스를 다시 복사하지 않아이 Custom source location방법을 사용할 수 없게되었습니다.

보너스 : stdlibc ++

C ++ 표준 라이브러리에 관심이 있다면 보너스 : GCC libstdc ++ C ++ 표준 라이브러리 소스를 편집하고 다시 작성하는 방법?


6

Nix http://nixos.org/nix/ 사용을 고려할 수 있습니까 ?

Nix는 다중 사용자 패키지 관리를 지원합니다. 여러 사용자가 공통 Nix 저장소를 안전하게 공유 할 수 있으며 소프트웨어를 설치하기 위해 루트 권한이 필요하지 않으며 다른 버전의 패키지를 설치 및 사용할 수 있습니다.


4

@msb는 안전한 솔루션을 제공합니다.

내가 한 때이 문제를 충족 import tensorflow as tf에 CONDA 환경에서 CentOS 6.5만 가지고있는 glibc-2.12.

ImportError: /lib64/libc.so.6: version `GLIBC_2.16' not found (required by /home/

몇 가지 세부 정보를 제공하고 싶습니다.

먼저 glibc홈 디렉토리에 설치 하십시오.

mkdir ~/glibc-install; cd ~/glibc-install
wget http://ftp.gnu.org/gnu/glibc/glibc-2.17.tar.gz
tar -zxvf glibc-2.17.tar.gz
cd glibc-2.17
mkdir build
cd build
../configure --prefix=/home/myself/opt/glibc-2.17  # <-- where you install new glibc
make -j<number of CPU Cores>  # You can find your <number of CPU Cores> by using **nproc** command
make install

둘째, 동일한 방법으로 patchelf 를 설치 하십시오 .

셋째, 파이썬을 패치하십시오.

[myself@nfkd ~]$ patchelf --set-interpreter /home/myself/opt/glibc-2.17/lib/ld-linux-x86-64.so.2 --set-rpath /home/myself/opt/glibc-2.17/lib/ /home/myself/miniconda3/envs/tensorflow/bin/python

@msb에서 언급했듯이

이제 tensorflow-2.0 alpha에서 사용할 수 있습니다 CentOS 6.5.

심판 : https://serverkurma.com/linux/how-to-update-glibc-newer-version-on-centos-6-x/


2

질문이 여전히 관련성이 있는지 확실하지 않지만 문제를 해결하는 또 다른 방법이 있습니다 .Docker. 소스 배포판 (개발에 사용 된 배포판)의 거의 빈 컨테이너를 설치하고 파일을 컨테이너에 복사 할 수 있습니다. 그렇게하면 chroot에 필요한 파일 시스템을 만들 필요가 없습니다.


1

두 번째 출력을 자세히 보면 새 라이브러리 위치가 사용 된 것을 볼 수 있습니다. glibc의 일부인 라이브러리가 여전히 없을 수 있습니다.

또한 프로그램에서 사용하는 모든 라이브러리가 해당 버전의 glibc에 대해 컴파일되어야한다고 생각합니다. 프로그램의 소스 코드에 액세스 할 수 있으면 새로운 컴파일이 최상의 솔루션 인 것 같습니다.


1

"고용 된 러시아어"가 가장 좋은 답변 중 하나이며 다른 모든 제안 된 답변이 효과가 없을 수도 있습니다. 그 이유는 단순히 응용 프로그램을 처음 만들 때 필요한 모든 API가 컴파일 타임에 해결되기 때문입니다. "ldd"u를 사용하면 정적으로 링크 된 모든 종속성을 볼 수 있습니다.

ldd /usr/lib/firefox/firefox
    linux-vdso.so.1 =>  (0x00007ffd5c5f0000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f727e708000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f727e500000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f727e1f8000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f727def0000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f727db28000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f727eb78000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f727d910000)

그러나 런타임에 firefox는 많은 다른 동적 라이브러리를로드합니다. 예를 들어 (firefox의 경우) 많은 "glib"레이블이있는 라이브러리가로드됩니다 (정적으로 링크되어 있지 않더라도).

 /usr/lib/x86_64-linux-gnu/libdbus-glib-1.so.2.2.2
 /lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0
 /usr/lib/x86_64-linux-gnu/libavahi-glib.so.1.0.2

여러 버전에서 한 버전의 이름이 다른 버전으로 소프트 링크 된 것을 볼 수 있습니다. 예 :

lrwxrwxrwx 1 root root     23 Dec 21  2014 libdbus-glib-1.so.2 -> libdbus-glib-1.so.2.2.2
-rw-r--r-- 1 root root 160832 Mar  1  2013 libdbus-glib-1.so.2.2.2

이는 하나의 시스템에 다른 버전의 "라이브러리"가 존재한다는 것을 의미합니다. 동일한 파일이므로 문제가되지 않으며 응용 프로그램에 여러 버전의 종속성이있는 경우 호환성을 제공합니다.

따라서 시스템 수준에서 모든 라이브러리는 서로 거의 상호 의존적이며 LD_PRELOAD 또는 LD_LIBRARY_PATH를 조작하여 라이브러리 로딩 우선 순위를 변경하면 도움이되지 않습니다.로드 할 수 있어도 런타임이 여전히 충돌 할 수 있습니다.

http://lightofdawn.org/wiki/wiki.cgi/-wiki/NewAppsOnOldGlibc

가장 좋은 대안은 chroot입니다 (ER에서 간단히 언급 함).이를 위해 일반적으로 / lib, / usr / lib /, / usr / lib / x86 등에서 시작하는 원래 바이너리 실행 환경 전체를 다시 만들어야합니다. "Buildroot"또는 YoctoProject를 사용하거나 기존 Distro 환경에서 tar를 사용할 수 있습니다. (Fedora / Suse 등).


0

Ubuntu 정확한 (glibc-2.15)에서 크롬 브라우저를 실행하고 싶을 때 "일반적인"메시지 "... libc.so.6 : version`GLIBC_2.19 'not found ..."가 나타났습니다. 파일이 영구적으로 필요하지는 않지만 시작에만 필요하다는 사실을 고려했습니다. 그래서 브라우저와 sudo에 필요한 파일을 수집하고 mini-glibc-2.19- 환경을 만들고 브라우저를 시작한 다음 원래 파일을 다시 복사했습니다. 필요한 파일은 RAM에 있으며 원본 glibc는 동일합니다.

as root
the files (*-2.15.so) already exist 

mkdir -p /glibc-2.19/i386-linux-gnu

/glibc-2.19/ld-linux.so.2 -> /glibc-2.19/i386-linux-gnu/ld-2.19.so
/glibc-2.19/i386-linux-gnu/libc.so.6 -> libc-2.19.so
/glibc-2.19/i386-linux-gnu/libdl.so.2 -> libdl-2.19.so
/glibc-2.19/i386-linux-gnu/libpthread.so.0 -> libpthread-2.19.so

mkdir -p /glibc-2.15/i386-linux-gnu

/glibc-2.15/ld-linux.so.2 -> (/glibc-2.15/i386-linux-gnu/ld-2.15.so)
/glibc-2.15/i386-linux-gnu/libc.so.6 -> (libc-2.15.so)
/glibc-2.15/i386-linux-gnu/libdl.so.2 -> (libdl-2.15.so)
/glibc-2.15/i386-linux-gnu/libpthread.so.0 -> (libpthread-2.15.so)

브라우저를 실행하는 스크립트 :

#!/bin/sh
sudo cp -r /glibc-2.19/* /lib
/path/to/the/browser &
sleep 1
sudo cp -r /glibc-2.15/* /lib
sudo rm -r /lib/i386-linux-gnu/*-2.19.so
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.