linuxfromscratch:12.1:098-gcc-13.2.0

Linux From Scratch - Version 12.1-systemd
Chapter 8. Installing Basic System Software
이전 위로 / 처음으로 다음
Shadow-4.14.5 Ncurses-6.4-20230520

GCC 패키지에는 C 컴파일러와 C++ 컴파일러가 포함된 GNU 컴파일러 컬렉션이 포함되어 있습니다.

  • 빌드 시간: 42 SBU (테스트 포함)
  • 디스크 공간: 5.5 GB

x86_64에서 빌드하는 경우 64비트 라이브러리의 기본 디렉토리 이름을 “lib”로 변경합니다.

case $(uname -m) in
  x86_64)
    sed -e '/m64=/s/lib64/lib/' \
        -i.orig gcc/config/i386/t-linux64
  ;;
esac

GCC 문서에서는 전용 빌드 디렉터리에 GCC를 빌드할 것을 권장합니다.

mkdir -v build
cd       build

GCC 컴파일을 준비합니다.

../configure --prefix=/usr            \
             LD=ld                    \
             --enable-languages=c,c++ \
             --enable-default-pie     \
             --enable-default-ssp     \
             --disable-multilib       \
             --disable-bootstrap      \
             --disable-fixincludes    \
             --with-system-zlib

GCC는 7가지 컴퓨터 언어를 지원하지만 대부분의 컴퓨터 언어에 대한 전제 조건이 되는 패키지가 아직 설치되지 않았습니다. GCC에서 지원되는 모든 언어를 빌드하는 방법에 대한 지침은 BLFS Book GCC 페이지를 참조하세요.

configure 옵션 설명

  • LD=ld
    크로스 빌드된 버전 대신 이 장의 앞부분에서 빌드한 Binutils 패키지에서 설치된 ld 프로그램을 사용하도록 합니다.
  • –disable-fixincludes
    기본적으로 GCC를 설치하는 동안 일부 시스템 헤더는 GCC와 함께 사용하도록 “고정”됩니다. 이는 최신 Linux 시스템에는 필요하지 않으며 GCC를 설치한 후 패키지를 다시 설치하는 경우 잠재적으로 해로울 수 있습니다. 이 스위치는 GCC가 헤더를 “고정”하지 못하도록 합니다.
  • –with-system-zlib
    GCC가 소스트리에 포함된 라이브러리가 아닌 시스템에 설치된 Zlib 라이브러리에 링크하도록 지시합니다.

참고
위치 독립 실행 파일(PIE)는 메모리 어디에서나 로드할 수 있는 바이너리 프로그램입니다. PIE를 사용하지 않으면 주소 공간 레이아웃 무작위화(ASLR)라는 보안 기능을 공유 라이브러리에는 적용할 수 있지만 실행 파일 자체에는 적용할 수 없습니다. PIE를 활성화하면 공유 라이브러리 외에 실행 파일에도 ASLR을 적용할 수 있으며 실행 파일의 민감한 코드나 데이터의 고정 주소를 기반으로 하는 일부 공격을 완화할 수 있습니다.

스택 스매싱 보호(SSP)는 매개변수 스택이 손상되지 않도록 하는 기술입니다. 예를 들어 스택이 손상되면 서브루틴의 반환 주소가 변경되어 프로그램이나 공유 라이브러리에 존재하거나 공격자가 어떤 식으로든 삽입한 위험한 코드로 제어권이 이전될 수 있습니다.

패키지를 컴파일합니다.

make

중요
GCC용 테스트 스위트는 매우 중요하지만 시간이 오래 걸립니다. LFS를 처음 읽는 독자는 테스트 스위트를 실행하는 것이 좋습니다. 아래의 make -k check 명령에 -j<x> 를 추가하면 테스트 실행 시간을 크게 줄일 수 있습니다. 여기서 <x>는 시스템의 CPU 코어 수입니다.

GCC 테스트 스위트의 한 테스트 세트는 기본 스택을 소진하는 것으로 알려져 있으므로 테스트를 실행하기 전에 스택 크기를 늘리세요.

ulimit -s 32768

root 권한이 없는 사용자로 결과를 테스트하고, 오류가 발생해도 계속 진행합니다.

chown -R tester .
su tester -c "PATH=$PATH make -k check"

테스트 스위트 결과의 요약을 추출하려면 다음을 실행합니다.

../contrib/test_summary

요약만 필터링하려면 파이프를 통해 grep -A7 Summ 실행합니다..

결과는 LFS 12.1 Build LogGCC Test-Result 에 있는 결과와 비교할 수 있습니다.

8개의 gcc 테스트(185,000개 이상 중): pr56837.canalyzer 디렉터리에 있는 7개의 테스트가 실패하는 것으로 알려져 있습니다. libstdc++ 테스트 1개(15,000개 이상 중)인 copy.cc는 실패하는 것으로 알려져 있습니다. g++의 경우, 21개 테스트(약 25만 개 중)가 실패합니다: 14개의 “AddressSanitizer*” 테스트와 7개의 interception-malloc-test-1.C 테스트가 실패하는 것으로 알려져 있습니다. 또한 하드웨어가 AVX를 지원하지 않는 경우 vect 디렉토리에 있는 여러 테스트가 실패하는 것으로 알려져 있습니다.

예상치 못한 몇 가지 실패를 항상 피할 수는 없습니다. GCC 개발자는 일반적으로 이러한 문제를 알고 있지만 아직 해결하지 못했습니다. 테스트 결과가 위 URL의 테스트 결과와 크게 다르지 않는 한 계속 진행해도 안전합니다.

패키지를 설치합니다.

make install

현재 GCC 빌드 디렉터리는 tester가 소유하고 있으며 설치된 헤더 디렉터리(및 해당 콘텐츠)의 소유권이 올바르지 않습니다. 소유권을 root 사용자 및 그룹으로 변경하세요.

chown -v -R root:root \
    /usr/lib/gcc/$(gcc -dumpmachine)/13.2.0/include{,-fixed}

“관습적인” 이유로 FHS에 필요한 심볼릭 링크를 생성합니다.

ln -svr /usr/bin/cpp /usr/lib

많은 패키지가 C 컴파일러를 호출할 때 cc라는 이름을 사용합니다. 우리는 이미 gcc-pass2에서 cc를 심볼릭 링크로 만들었으므로, 그 man 페이지도 심볼릭 링크로 만듭니다.

ln -sv gcc.1 /usr/share/man/man1/cc.1

호환성 심볼릭 링크를 추가하여 링크 시 최적화(LTO)로 프로그램을 빌드할 수 있도록 합니다.

ln -sfv ../../libexec/gcc/$(gcc -dumpmachine)/13.2.0/liblto_plugin.so \
        /usr/lib/bfd-plugins/

이제 최종 툴체인이 준비되었으므로 컴파일과 링킹이 예상대로 작동하는지 다시 한 번 확인하는 것이 중요합니다. 이를 위해 몇 가지 정상 검사를 수행합니다.

오류가 없어야 하며 마지막 명령의 출력은 다음과 같아야 합니다(동적 링커 이름에 플랫폼별 차이가 있을 수 있음).

echo 'int main(){}' > dummy.c
cc dummy.c -v -Wl,--verbose &> dummy.log
readelf -l a.out | grep ': /lib'
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]

이제 올바른 시작 파일을 사용하도록 설정되어 있는지 확인합니다.

마지막 명령의 출력은 다음과 같아야 합니다.

grep -E -o '/usr/lib.*/S?crt[1in].*succeeded' dummy.log
/usr/lib/gcc/x86_64-pc-linux-gnu/13.2.0/../../../../lib/Scrt1.o succeeded
/usr/lib/gcc/x86_64-pc-linux-gnu/13.2.0/../../../../lib/crti.o succeeded
/usr/lib/gcc/x86_64-pc-linux-gnu/13.2.0/../.../../../lib/crtn.o succeeded

머신 아키텍처에 따라 위의 내용은 약간 다를 수 있습니다. 차이점은 /usr/lib/gcc 뒤의 디렉토리 이름입니다. 여기서 중요한 것은 gcc/usr/lib 디렉터리에서 세 개의 crt*.o 파일을 모두 찾았다는 것입니다.

컴파일러가 올바른 헤더 파일을 검색하고 있는지 확인합니다.

이 명령은 다음과 같은 출력을 반환해야 합니다.

grep -B4 '^ /usr/include' dummy.log
#include <...> search starts here.
 /usr/lib/gcc/x86_64-pc-linux-gnu/13.2.0/include
 /usr/local/include
 /usr/lib/gcc/x86_64-pc-linux-gnu/13.2.0/include-fixed
 /usr/include

다시 말하지만, 시스템 아키텍처에 따라 대상 삼중 항의 이름을 딴 디렉터리는 위와 다를 수 있습니다.

다음으로 새 링커가 올바른 검색 경로와 함께 사용되고 있는지 확인합니다. 경로에 '-linux-gnu'가 포함된 구성 요소에 대한 참조는 무시해야 하지만, 나머지 항목은 아래의 출력과 같아야 합니다.

grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'
SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib64")
SEARCH_DIR("/usr/local/lib64")
SEARCH_DIR("/lib64")
SEARCH_DIR("/usr/lib64")
SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib")
SEARCH_DIR("/usr/local/lib")
SEARCH_DIR("/lib")
SEARCH_DIR("/usr/lib");

32비트 시스템에서는 몇 가지 다른 디렉터리를 사용할 수 있습니다. 예를 들어 다음은 i686 컴퓨터의 출력입니다.

grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'
SEARCH_DIR("/usr/i686-pc-linux-gnu/lib32")
SEARCH_DIR("/usr/local/lib32")
SEARCH_DIR("/lib32")
SEARCH_DIR("/usr/lib32")
SEARCH_DIR("/usr/i686-pc-linux-gnu/lib")
SEARCH_DIR("/usr/local/lib")
SEARCH_DIR("/lib")
SEARCH_DIR("/usr/lib");

다음으로 올바른 libc를 사용하고 있는지 확인합니다.

명령의 출력은 다음과 같아야 합니다.

grep "/lib.*/libc.so.6" dummy.log
attempt to open /usr/lib/libc.so.6 succeeded

GCC가 올바른 동적 링커를 사용하고 있는지 확인합니다. 명령의 출력은 다음과 같아야 합니다(플랫폼에 따라 동적 링커 이름이 다를 수 있음).

grep found dummy.log
found ld-linux-x86-64.so.2 at /usr/lib/ld-linux-x86-64.so.2

위와 같이 출력이 나타나지 않거나 아무것도 출력되지 않는다면 심각한 문제가 있는 것입니다. 각 단계를 조사하고 역추적하여 문제의 원인을 찾아서 해결하세요. 계속 진행하기 전에 모든 문제를 해결해야 합니다.

모든 것이 올바르게 작동하면 테스트 파일을 정리합니다.

rm -v dummy.c a.out dummy.log

마지막으로 잘못 배치된 파일을 이동합니다.

mkdir -pv /usr/share/gdb/auto-load/usr/lib
mv -v /usr/lib/*gdb.py /usr/share/gdb/auto-load/usr/lib


  • 설치된 프로그램:
    c++, cc(gcc 링크), cp, g++, gcc, gcc-ar, gcc-nm, gcc-ranlib, gcov, gcov-dump, gcov-tool 및 lto-dump
  • 설치된 라이브러리
    libasan.{a,so}, libatomic.{a,so}, libcc1.so, libgcc.a, libgcc_eh.a, libgcc_s.so, libgcov.a, libgomp.{a,so}, libhwasan.{a,so}, libitm.{a,so}, liblsan.{a,so}, liblto_plugin. so, libquadmath.{a,so}, libssp.{a,so}, libssp_nonshared.a, libstdc++.{a,so}, libstdc++exp.a, libstdc++fs.a, libsupc++.a, libtsan.{a,so} 및 libubsan.{a,so}
  • 설치된 디렉터리
    /usr/include/c++, /usr/lib/gcc, /usr/libexec/gcc, /usr/share/gcc-13.2.0

간략한 설명

  • c++
    C++ 컴파일러
  • cc
    C 컴파일러
  • cpp
    컴파일러가 소스 파일에서 #include, #define 및 이와 유사한 지시어를 확장하는 데 사용하는 C 전처리기입니다.
  • g++
    C++ 컴파일러
  • gcc
    C 컴파일러
  • gcc-ar
    명령줄에 플러그인을 추가하는 ar 래퍼. 이 프로그램은 “LTO(링크 타임 최적화)“를 추가하는 데만 사용되며 기본 빌드 옵션에서는 유용하지 않습니다.
  • gcc-nm
    명령줄에 플러그인을 추가하는 nm 래퍼. 이 프로그램은 “LTO(링크 타임 최적화)“를 추가하는 데만 사용되며 기본 빌드 옵션에서는 유용하지 않습니다.
  • gcc-ranlib
    명령줄에 플러그인을 추가하는 ranlib 래퍼. 이 프로그램은 “LTO(링크 타임 최적화)“를 추가하는 데만 사용되며 기본 빌드 옵션에서는 유용하지 않습니다.
  • gcov
    커버리지 테스트 도구로, 프로그램을 분석하여 최적화가 가장 큰 효과를 낼 수 있는 위치를 결정하는 데 사용됩니다.
  • gcov-dump
    오프라인 gcda 및 gcno 프로파일 덤프 도구
  • gcov-tool
    오프라인 gcda 프로파일 처리 도구
  • lto-dump
    LTO가 활성화된 상태에서 GCC에서 생성된 오브젝트 파일을 덤프하는 도구
  • libasan
    Address Sanitizer 런타임 라이브러리
  • libatomic
    GCC atomic 빌트인 런타임 라이브러리
  • libcc1
    GDB가 GCC를 사용할 수 있게 해주는 라이브러리
  • libgcc
    gcc에 대한 런타임 지원을 포함합니다.
  • libgcov
    이 라이브러리는 GCC가 프로파일링을 활성화하도록 지시할 때 프로그램에 연결됩니다.
  • libgomp
    C/C++ 및 포트란에서 다중 플랫폼 공유 메모리 병렬 프로그래밍을 위한 OpenMP API의 GNU 구현
  • libhwasan
    하드웨어 지원 Address Sanitizer 런타임 라이브러리
  • libitm
    GNU 트랜잭션 메모리 라이브러리
  • liblsan
    Leak Sanitizer 런타임 라이브러리
  • liblto_plugin
    Binutils가 LTO가 활성화된 상태에서 GCC에서 생성된 객체 파일을 처리할 수 있도록 하는 GCC의 LTO 플러그인
  • libquadmath
    GCC 4배 정밀도 연산 라이브러리 API
  • libssp
    GCC의 SSP1) 기능을 지원하는 루틴이 포함되어 있습니다. Glibc에서도 이러한 루틴을 제공하기 때문에 일반적으로는 사용되지 않습니다.
  • libstdc++
    표준 C++ 라이브러리
  • libstdc++exp
    실험적인 C++ 컨트랙트 라이브러리
  • libstdc++fs
    ISO/IEC TS 18822:2015 파일시스템 라이브러리
  • libsupc++
    C++ 프로그래밍 언어에 대한 지원 루틴을 제공합니다.
  • libtsan
    Thread Sanitizer 런타임 라이브러리
  • libubsan
    Undefined Behavior Sanitizer 런타임 라이브러리

1)
stack-smashing protection
  • linuxfromscratch/12.1/098-gcc-13.2.0.txt
  • 마지막으로 수정됨: 2024/06/15 11:43
  • 저자 baecy