^ Linux From Scratch - Version 12.1-systemd ^^^ ^ Chapter 8. Installing Basic System Software ^^^ |[[.:097-shadow-4.14.5|이전]] | [[.:08-installing_basic_system_software|위로]] / [[.:12.1|처음으로]] | [[.:099-ncurses-6.4-20230520|다음]]| |Shadow-4.14.5 | Ncurses-6.4-20230520| ---- ===== 8.28. GCC-13.2.0 ===== GCC 패키지에는 C 컴파일러와 C++ 컴파일러가 포함된 GNU 컴파일러 컬렉션이 포함되어 있습니다. * **빌드 시간:** 42 SBU (테스트 포함) * **디스크 공간:** 5.5 GB ---- ==== 8.28.1. GCC 설치 ==== 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에서 지원되는 모든 언어를 빌드하는 방법에 대한 지침은 [[https://www.linuxfromscratch.org/blfs/view/stable-systemd/general/gcc.html|BLFS Book GCC]] 페이지를 참조하세요. === configure 옵션 설명 === * //LD=ld// \\ 크로스 빌드된 버전 대신 이 장의 앞부분에서 빌드한 Binutils 패키지에서 설치된 **ld** 프로그램을 사용하도록 합니다. * //--disable-fixincludes// \\ 기본적으로 GCC를 설치하는 동안 일부 시스템 헤더는 GCC와 함께 사용하도록 "고정"됩니다. 이는 최신 Linux 시스템에는 필요하지 않으며 GCC를 설치한 후 패키지를 다시 설치하는 경우 잠재적으로 해로울 수 있습니다. 이 스위치는 GCC가 헤더를 "고정"하지 못하도록 합니다. * //--with-system-zlib// \\ GCC가 소스트리에 포함된 라이브러리가 아닌 시스템에 설치된 Zlib 라이브러리에 링크하도록 지시합니다. **참고** \\ [[wpko>위치 독립 코드|위치 독립 실행 파일]](PIE)는 메모리 어디에서나 로드할 수 있는 바이너리 프로그램입니다. PIE를 사용하지 않으면 주소 공간 레이아웃 무작위화([[wp>Address space layout randomization|ASLR]])라는 보안 기능을 공유 라이브러리에는 적용할 수 있지만 실행 파일 자체에는 적용할 수 없습니다. PIE를 활성화하면 공유 라이브러리 외에 실행 파일에도 ASLR을 적용할 수 있으며 실행 파일의 민감한 코드나 데이터의 고정 주소를 기반으로 하는 일부 공격을 완화할 수 있습니다. 스택 스매싱 보호(SSP)는 매개변수 스택이 손상되지 않도록 하는 기술입니다. 예를 들어 스택이 손상되면 서브루틴의 반환 주소가 변경되어 프로그램이나 공유 라이브러리에 존재하거나 공격자가 어떤 식으로든 삽입한 위험한 코드로 제어권이 이전될 수 있습니다. 패키지를 컴파일합니다. make **중요** \\ GCC용 테스트 스위트는 매우 중요하지만 시간이 오래 걸립니다. LFS를 처음 읽는 독자는 테스트 스위트를 실행하는 것이 좋습니다. 아래의 ''make -k check'' 명령에 ''-j'' 를 추가하면 테스트 실행 시간을 크게 줄일 수 있습니다. 여기서 는 시스템의 CPU 코어 수입니다. GCC 테스트 스위트의 한 테스트 세트는 기본 스택을 소진하는 것으로 알려져 있으므로 테스트를 실행하기 전에 스택 크기를 늘리세요. ulimit -s 32768 //root// 권한이 없는 사용자로 결과를 테스트하고, 오류가 발생해도 계속 진행합니다. chown -R tester . su tester -c "PATH=$PATH make -k check" 테스트 스위트 결과의 요약을 추출하려면 다음을 실행합니다. ../contrib/test_summary 요약만 필터링하려면 파이프를 통해 ''grep -A7 Summ'' 실행합니다.. 결과는 [[https://www.linuxfromscratch.org/lfs/build-logs/12.1/|LFS 12.1 Build Log]] 및 [[https://gcc.gnu.org/ml/gcc-testresults/|GCC Test-Result]] 에 있는 결과와 비교할 수 있습니다. 8개의 gcc 테스트(185,000개 이상 중): ''pr56837.c'' 및 ''analyzer'' 디렉터리에 있는 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} "관습적인" 이유로 [[https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch03s09.html|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 ---- ==== 8.28.2. GCC 패키지 구성 ==== * **설치된 프로그램:** \\ 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 \\ [[https://gcc.gnu.org/wiki/Atomic/GCCMM/AtomicTypes|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 [[wpko>부동소수점#규격|4배 정밀도]] 연산 라이브러리 API * libssp \\ GCC의 SSP((stack-smashing protection)) 기능을 지원하는 루틴이 포함되어 있습니다. Glibc에서도 이러한 루틴을 제공하기 때문에 일반적으로는 사용되지 않습니다. * libstdc++ \\ 표준 C++ 라이브러리 * libstdc++exp \\ 실험적인 C++ 컨트랙트 라이브러리 * libstdc++fs \\ ISO/IEC TS 18822:2015 파일시스템 라이브러리 * libsupc++ \\ C++ 프로그래밍 언어에 대한 지원 루틴을 제공합니다. * libtsan \\ Thread Sanitizer 런타임 라이브러리 * libubsan \\ Undefined Behavior Sanitizer 런타임 라이브러리