g++ - 다른 버전의 GLIBC로 소스코드 빌드
임의의 버전으로 glibc 자체를 다운로드해 빌드할 수가 있군요. ^^ 가령, Ubuntu 20.04에는 2.31이 설치돼 있는데, 2.35를 가져와 이런 식으로 빌드할 수 있습니다.
$ mkdir $HOME/glibc/
$ cd $HOME/glibc
~/glibc$ wget http://ftp.gnu.org/gnu/libc/glibc-2.35.tar.gz
~/glibc$ tar -xvzf glibc-2.35.tar.gz
~/glibc$ mkdir build
~/glibc$ mkdir install
~/glibc$ cd build
~/glibc/build$ ~/glibc/glibc-2.35/configure --prefix=/opt/glibc-2.35
~/glibc/build$ make
~/glibc/build$ sudo make install // 출력 디렉터리를 /opt 하위로 지정했기 때문에 sudo 권한 필요
$ ls /opt/glibc-2.35
bin etc include lib sbin share usr var
$ /opt/glibc-2.35/bin/ldd --version
ldd (GNU libc) 2.35
...[생략]...
이렇게 빌드한 라이브러리를 어떻게 이용할 수 있을까요? 아래의 글을 보면,
Multiple glibc libraries on a single host
; https://stackoverflow.com/questions/847179/multiple-glibc-libraries-on-a-single-host
LD_LIBRARY_PATH로 시도했다는 질문이 나옵니다. 실제로 저도 그렇게만 적용했더니 Segmentation fault가 발생합니다.
$ ls /opt/glibc-2.35/lib/libc.so.6 -l
-rwxr-xr-x 1 root root 19111480 Jul 2 23:45 /opt/glibc-2.35/lib/libc.so.6
$ export LD_LIBRARY_PATH=/opt/glibc-2.35/lib
$ ls
Segmentation fault
답글에 나온 내용에 따르면 ld-linux.so.2는 링킹 시에 하드 코딩이 된다고 하는데요, ls의 경우 ld-linux-x86-64.so.2가 그것에 해당하는 듯합니다.
$ ldd /usr/bin/ls
linux-vdso.so.1 (0x00007ffe3a6e1000)
libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007fa4e1545000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa4e1353000)
libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007fa4e12c2000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fa4e12bc000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa4e15ab000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa4e1299000)
이 경로를
patchelf 등의 도구로 변경하거나, 빌드 시에 새로운 glibc 경로를 지정하는 것으로 해결할 수 있습니다. 직접 해볼까요? ^^ 일단 Ubuntu 20.04에서 아래의 과정을 실습하면 2.31 버전의 glibc를 사용한다고 나올 것입니다.
$ cat main.cpp
#include <cstdio>
#include <gnu/libc-version.h>
int main()
{
printf("gnu_get_libc_version() = %s\n", gnu_get_libc_version());
return 0;
}
$ g++ main.cpp -o testapp
$ ./testapp
gnu_get_libc_version() = 2.31
반면 새롭게 빌드한 glibc-2.35를 지정하면,
$ g++ main.cpp -o testapp -Wl,--rpath=/opt/glibc-2.35/lib -Wl,--dynamic-linker=/opt/glibc-2.35/lib/ld-linux-x86-64.so.2
$ ./testapp
gnu_get_libc_version() = 2.35
$ ldd testapp
linux-vdso.so.1 (0x00007ffe14c9c000)
libc.so.6 => /opt/glibc-2.35/lib/libc.so.6 (0x00007ff11791e000)
/opt/glibc-2.35/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007ff117b27000)
의도했던 대로 2.35 버전의 glibc를 사용하고 있습니다.
참고로, Visual Studio의 리눅스 프로젝트에서 glibc를 지정하려면
Linker / "Command Line"의 "Additional Options"에 다음과 같은 식으로 값을 지정하고 빌드하면 됩니다. (물론, 실제로 빌드가 되는 Remote Machine에 /opt/glibc-2.35가 구성돼 있어야 합니다.)
-Wl,--rpath=/opt/glibc-2.35/lib -Wl,--dynamic-linker=/opt/glibc-2.35/lib/ld-linux-x86-64.so.2
그렇다면, 저렇게 2.35 버전의 glibc 경로를 명시한 프로그램을, 원래 2.35가 설치된 환경에서 실행하면 어떻게 될까요? 가령, 위에서 빌드한 프로그램을 이미 2.35가 설치된 Ubuntu 22.04에서 실행하면,
$ ./testapp
-bash: ./testapp: No such file or directory
$ ldd testapp
linux-vdso.so.1 (0x00007fffe4f1a000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f30f0362000)
/opt/glibc-2.35/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007f30f0597000)
$ LD_LIBRARY_PATH=/lib64 ./testapp
-bash: ./testapp: No such file or directory
저렇게 오류가 발생합니다. 어쩔 수 없습니다, ld-linux-x86-64.so.2 경로가 하드코딩됐으므로, 이것을
patchelf 등의 도구로 변경해야 합니다.
$ patchelf --set-interpreter /lib64/ld-linux-x86-64.so.2 testapp
$ ldd testapp
linux-vdso.so.1 (0x00007ffc779ac000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f42708c7000)
/lib64/ld-linux-x86-64.so.2 (0x00007f4270afe000)
$ ./testapp
gnu_get_libc_version() = 2.35
configure 과정에서 이런 오류가 발생한다면?
~/glibc$ ~/glibc/glibc-2.35/configure --prefix=$HOME/glibc/glibc-2.35-install
...[생략]...
configure: error:
*** These critical programs are missing or too old: bison
*** Check the INSTALL file for required versions.
버전이 너무 낮아서일 수도 있지만 설치되지 않은 경우도 있습니다.
$ apt --installed list | grep bison
따라서 설치만 해주면 해결됩니다.
$ sudo apt install bison -y
$ apt --installed list | grep bison
bison/focal,now 2:3.5.1+dfsg-1 amd64 [installed]
참고로 bison도 업데이트할 수 있을 텐데 버전은 다음의 문서에서 확인할 수 있습니다.
Package bison
; https://packages.ubuntu.com/search?keywords=bison>
20.04의 다음 버전인 "jammy (22.04LTS)"에는 "2:3.8.2" 버전이 있는데요, 따라서 다음과 같이 업데이트할 수 있을 것입니다.
mkdir $HOME/bison
cd $HOME/bison
wget https://ftp.gnu.org/gnu/bison/bison-3.8.2.tar.gz
tar xf bison-3.8.2.tar.gz
cd bison-3.8.2
./configure --prefix=$HOME/bison/install
make
make install
PATH=$HOME/bison/install/bin:$PATH
configure 과정에서 이런 경고가 발생한다면?
~/glibc$ ~/glibc/glibc-2.35/configure --prefix=$HOME/glibc/glibc-2.35-install
...[생략]...
*** These auxiliary programs are missing or incompatible versions: msgfmt makeinfo
*** some features or tests will be disabled.
*** Check the INSTALL file for required versions.
경고라서 무시할 수 있지만, 정히 찜찜하다면 어렵지 않으니 그냥 설치(또는 업데이트)할 수 있습니다.
$ sudo apt install gettext texinfo -y
$ apt --installed list | grep "texinfo\|gettext"
gettext/focal,now 0.19.8.1-10build1 amd64 [installed]
texinfo/focal,now 6.7.0.dfsg.2-5 amd64 [installed]
...[생략]...
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]