GCC(GNU Compiler Collection,GNU編譯器合集)是linux以及其餘類UNIX平臺上進行開源項目,軟件開發等必不可少的工具鏈組成之一。(其餘的還有clang以及llvm等編譯器)linux
對於程序員以及系統管理員而言,常常須要從軟件的源碼進行手動編譯安裝,c++
不管是configure腳本,仍是make工具,最終都須要調用gcc(或者其它編譯器)來進行實際的編譯工做。程序員
另外,各類軟件也常常須要使用gcc的新版特性,而且與舊版gcc共存,根據實際的需求進行調用。bootstrap
實驗環境:VMware Workstation Pro 14(試用版) 系統平臺: CentOS release 6.9 (Final) 內核 2.6.32-696.el6.x86_64 軟件包:minimal最小化安裝
glibcvim
GNU C Library https://www.gnu.org/ GNU C庫項目提供了 GNU系統和GNU / Linux系統的核心庫,以及許多其餘使用Linux做爲內核的系統。glibc是Linux系統中最底層的API,幾乎其它任何的運行庫都要依賴glibc。這些庫提供了關鍵的API, 包括ISO C11,POSIX.1-2008,BSD,操做系統特定的API等等。這些API包括open, read,write,malloc,printf, getaddrinfo,dlopen,pthread_create, crypt,login,exit等基礎設施。 GNU C庫被設計成一個向後兼容、便攜、高性能的ISO C庫。它旨在遵循全部相關標準,包括ISO C11,POSIX.1-2008和IEEE 754-2008。 該項目始於1988年,已有近30年的歷史。 沒有這個軟件包,Linux系統將不能正常工做。 默認最小化安裝已經隨系統安裝好 #ldd --version ldd (GNU libc) 2.12 #rpm -qa|grep glibc glibc-common-2.12-1.209.el6.x86_64 glibc-2.12-1.209.el6.x86_64 glibc-headers-2.12-1.209.el6.x86_64 glibc-devel-2.12-1.209.el6.x86_64
Glibc是非交叉編譯環境下,從源碼編譯安裝gcc必備的。centos
若是是交叉編譯的環境,即在一種硬件架構/操做系統上編譯(宿主機),可是生成的二進制可執行文件要在另外一種硬件架構/操做系統上運行(目標機),架構
在這種狀況下,不能依賴宿主機器上已編譯的C庫,最好是自行下載glibc的源碼並編譯。app
glibc-static編輯器
GNU C標準庫的靜態版,只有在用於 -static 靜態連接時才須要, glibc-static是非交叉編譯環境下,從源碼編譯安裝gcc必備的,並且它依賴於Glibc(要先裝Glibc) 默認最小化安裝並不會預裝glibc-static
libstdc++ide
兼容GCC的C++標準庫 libc++是針對clang編譯器特別重寫的C++標準庫,那libstdc++天然就是gcc的事兒了。libstdc++與gcc的關係就像clang與libc++。 默認最小化安裝已經隨系統安裝好 #rpm -qa|grep libstdc++ libstdc++-4.4.7-18.el6.x86_64 libstdc++-devel-4.4.7-18.el6.x86_64 #rpm -ql libstdc++-4.4.7-18.el6.x86_64 /usr/lib64/libstdc++.so.6 /usr/lib64/libstdc++.so.6.0.13
gcc
由於它本來只能處理C語言。GCC在發佈後很快地獲得擴展,變得可處理C++。以後也變得可處理Fortran、Pascal、Objective-C、Java、Ada,Go與其餘語言。 許多操做系統,包括許多類Unix系統,如Linux及BSD家族都採用GCC做爲標準編譯器。 默認最小化安裝並不會預裝gcc 從源碼編譯安裝新版gcc前,要求系統上已經安裝有舊版gcc
gcc-c++
GNU編譯器合集的c++加強支持包,它向gcc的c++編譯器提供了更多對當前c++標準規範的支持,包含模板和錯誤處理。 默認最小化安裝並不會預裝gcc-c++ gcc-c++ 還須要額外的 libstdc++ 支持
爲了能順利的yum安裝,從新配置了光盤和aliyun的yum源
請自行參考 https://mirrors.aliyun.com/help/centos
所以,編譯安裝新版本的gcc組件,須要準備如下3個軟件包
gcc gcc-c++ glibc-static
#yum install gcc gcc-c++ glibc-static
會自動解決依賴關係
驗證這3個軟件包的狀態
#rpm -qa|grep gcc;rpm -qa|grep glibc-static libgcc-4.4.7-18.el6.x86_64 gcc-4.4.7-18.el6.x86_64 gcc-c++-4.4.7-18.el6.x86_64 glibc-static-2.12-1.209.el6_9.2.x86_64 #which gcc;which g++ /usr/bin/gcc /usr/bin/g++ #rpm -ql glibc-static /usr/lib64/libBrokenLocale.a /usr/lib64/libanl.a /usr/lib64/libc.a /usr/lib64/libc_stubs.a /usr/lib64/libcrypt.a /usr/lib64/libdl.a /usr/lib64/libm.a /usr/lib64/libnsl.a /usr/lib64/libpthread.a /usr/lib64/libresolv.a /usr/lib64/librt.a /usr/lib64/libutil.a
編譯器( cc1 )預連接器( collect2 )連接器 ( ld ) 彙編器 ( as )
cc1負責對源文件實際的編譯工做;
collect2進行預連接處理,實際的連接由連接器ld完成;
安裝到如下路徑
#ls /usr/libexec/gcc/x86_64-redhat-linux/4.4.7 cc1 cc1plus collect2 #which ld /usr/bin/ld
頭文件在如下目錄
#ls /usr/lib/gcc/x86_64-redhat-linux/4.4.7/include/ abmintrin.h bmmintrin.h f16cintrin.h iso646.h mmintrin.h pmmintrin.h stdbool.h tbmintrin.h wmmintrin.h ammintrin.h cpuid.h float.h limits.h mm_malloc.h popcntintrin.h stddef.h tmmintrin.h x86intrin.h avxintrin.h cross-stdarg.h fma4intrin.h lwpintrin.h nmmintrin.h smmintrin.h stdfix.h unwind.h xmmintrin.h bmiintrin.h emmintrin.h immintrin.h mm3dnow.h omp.h stdarg.h syslimits.h varargs.h xopintrin.h
gcc4.4.7版本開始,官方推薦使用單獨的目錄,而不是在解壓gcc源碼後的目錄中進行編譯,
緣由在於:
優化以及生成性能更好的二進制可執行文件;
避免不可預期的錯誤發生;
避免污染源碼所在目錄;
所以,咱們須要在文件系統的指定目錄下創建1個用於編譯的目錄
並使用configure腳本的 --prefix=/usr/local/[自定義的路徑名稱] 來指定安裝目錄,這樣,gcc的可執行文件,庫文件,頭文件就會井井有理分別存放在相應的子目錄下,
之後不用時直接 rm -rf 整個安裝路徑就能夠了。這就是編譯安裝的好處,你清晰的知道全部產生的文件來自哪裏。
如下操做如無特殊說明 ,所有在/app/sdb目錄操做。 #mkdir gcc-build
CentOS 7 使用4.8.5,通常狀況下這個版本的編譯器已經知足須要了。
考慮到與Centos 7的兼容性,這裏選擇了gcc 4.8.5
去官網下載gcc4.8.5源碼包
ftp://gcc.gnu.org/pub/gcc/releases
對應版本的目錄下會有md5.sum等校驗信息文件,下載到本地後,運行md5sum進行比對,若是值不同,則說明下載過程當中有錯誤,須要從新下載。 #md5sum gcc-4.8.5.tar.gz bfe56e74d31d25009c8fb55fd3ca7e01 gcc-4.8.5.tar.gz
編譯安裝 GCC 須要依賴 cloog gmp mpc mpfr isl
其中 isl 並非編譯gcc必需,可是能夠優化生成的可執行文件,所以推薦下載。
特別提醒:
不一樣版本軟件的相互組合,可能並不會預期的正常編譯,致使後面的make第一階段make退出。下面是我測試了幾種組合獲得的結果,儘量的使用了高版本。
聯合編譯時間較長,但願這表能幫助你節約時間。
GNU軟件均可以到如下網址下載,isl不是GNU項目,只能到官方網下載 https://ftp.gnu.org/ mpfr https://ftp.gnu.org/gnu/mpfr/ gmp https://gmplib.org/ mpc http://www.multiprecision.org/mpc/ cloog http://www.cloog.org/ isl http://isl.gforge.inria.fr/
所有下載好了 #tree . ├── gcc-build └── src ├── cloog-0.18.4.tar.gz ├── gcc-4.8.5.tar.gz ├── gmp-6.1.2.tar.xz ├── isl-0.14.tar.gz ├── mpc-1.0.3.tar.gz └── mpfr-3.1.4.tar.gz
#tar xvf src/gcc-4.8.5.tar.gz -C /app/sdb/
將這5個依賴庫的源碼包,解壓到gcc源碼目錄下,因爲gcc編譯規則只能識別不帶版本號的子目錄名稱,
所以,還須要將其重命名。這樣在gcc編譯的時候,會自動編譯相關的組件
#tar xvf src/cloog-0.18.4.tar.gz -C gcc-4.8.5/ #tar xvf src/gmp-6.1.2.tar.xz -C gcc-4.8.5/ #tar xvf src/isl-0.14.tar.gz -C gcc-4.8.5/ #tar xvf src/mpc-1.0.3.tar.gz -C gcc-4.8.5/ #tar xvf src/mpfr-3.1.4.tar.bz2 -C gcc-4.8.5/ #mv gcc-4.8.5/cloog-0.18.4 gcc-4.8.5/cloog #mv gcc-4.8.5/gmp-6.1.2/ gcc-4.8.5/gmp #mv gcc-4.8.5/isl-0.14/ gcc-4.8.5/isl #mv gcc-4.8.5/mpc-1.0.3/ gcc-4.8.5/mpc #mv gcc-4.8.5/mpfr-3.1.4/ gcc-4.8.5/mpfr 完成以後,目錄結構應該是相似如下的: gcc-4.8.5/ ├── cloog ├── gmp ├── isl ├── mpc ├── mpfr
因爲以前使用yum安裝gcc舊版本編譯器的時候,安裝了一些與編譯依賴包相同的包,會不會產生衝突?
結論是:不會,由於這5個依賴庫是編譯gcc源碼時才須要的,並且使用單獨的編譯目錄來存儲中間編譯好的文件,就是爲了不這種問題。
固然,還有更簡單的方法,運行源碼包中的contrib/download_prerequisites這個腳本,會自動下載相應的依賴包。能夠查看這個腳本內容。通常來講,較新的源碼包會下載較新的依賴包。
不過,下載速度真的是慢,建議自行下載吧。
至此,準備工做就緒。
--prefix=/usr/local/gcc-4.8.5 新版本最終安裝的目錄 --with-pkgversion=version 指定一個標識你的包的字符串。您可能但願包含內部版本號或生成日期。這個版本的字符串將被包含在輸出中gcc --version。這個後綴不會替換默認的版本字符串,只會替代'GCC'部分。 默認值是'GCC」。 --enable-bootstrap 也就是進行冗餘的編譯檢查工做。非交叉編譯環境下,默認已經將該值設爲 enable,能夠不用顯式指定;交叉編譯環境下,須要顯式將其值設爲 disable。 --enable-checking=release 以軟件發佈版的標準來對編譯時生成的代碼進行一致性檢查;設置該選項爲enable並不會改變編譯器生成的二進制結果, 可是會致使編譯的時間增長;該選項僅支持gcc編譯器; 整體而言,對於上面這個選項,機器的硬件配置較低,以及不肯等待過久編譯時間的童鞋,能夠設置爲 disable;可是這會增長產生未預期的錯誤的風險,因此應該慎用。 能夠同時設置 --disable-bootstrap 與 --disable-checking,這對編譯過程的提速頗有幫助。 --enable-languages=c,c++ 目前,可使用任何以下: all,default,ada,c,c++,fortran,go,jit,lto,objc,obj-c++。若是 all被指定,則全部可用的語言都被創建。 jit語言是一個例外 的語言。這裏按需只開啓了c和c++,由於支持的語言越多,就須要安裝越多的相應靜態與動態庫,還有五花八門的依賴庫,這會讓管理變得困難,體積也會變得龐大。 --disable-multilib 生成多個平臺的代碼,好比:64bit機器,同時能夠產生32和64兩種格式;若是你的操做系統是64位,默認就已經設置爲 enable,這意味着用gcc編譯其它源文件時能夠經過 -m32 選項來決定是否生成32位機器代碼。若是在64位系統上,要禁止生成32位代碼, 設置 --disable-multilib。 --enable-gather-detailed-mem-stats 容許收集詳細的內存使用信息,若是設置該參數爲 enable,則未來編譯好的gcc可執行程序,能夠經過 -fmem-report 選項來輸出編譯其它程序時的實時內存使用狀況。 --with-long-double-128 指定long double類型的默認值是128位。若是使用--without-long-double-128, long double將默認64位,與double類型相同。 若是使用GNU C Library 2.4或更高版本,則默認爲128位。
#cd gcc-build/ #/app/sdb/gcc-4.8.5/configure --prefix=/usr/local/gcc-4.8.5 --enable-checking=release --enable-bootstrap --enable-languages=c,c++ --disable-multilib --enable-gather-detailed-mem-stats --with-long-double-128 會在gcc-build目錄生成如下4個文件 #ls config.log config.status Makefile serdep.tmp
使用vim等編輯工具打開config.log,查找error關鍵字,搜索configure檢測到的潛在配置錯誤和警告,這對後面的make階段可否正常編譯相當重要,所以要謹慎對待。若是沒有任何與error相關的警告信息,那麼就認爲能夠執行 make 命令。
conftest.cpp:11:2: error: #error -static-libstdc++ not implemented 忽略它也能正常編譯,未能找到解決的方法。
若是須要從新configure或make中途出錯退出,最好把當前目錄下的全部東西都刪除乾淨。
也能夠執行下面指令清空 編譯目錄下的相關文件,包括makefile
# make distclean
make命令中的-j 指定同時開啓的進程數,要充分發揮多核處理器的並行執行優點,這個值應該是處理器芯片上物理核心的2倍。CPU給不給力就看這個了。
#lscpu |grep -A 1 'Model name' Model name: Intel(R) Core(TM) i5-5200U CPU @ 2.20GHz Stepping: 4
這條指令重點是make -j 8 ,先後加的date指令是爲了統計編譯時間的。 #date +%F-%T >> /app/time.txt && make -j 8 && date +%F-%T >> /app/time.txt
若是看到如下相似字樣,恭喜你,編譯經過了。 make[4]: Leaving directory `/app/sdb/gcc-build/x86_64-unknown-linux-gnu/libmudflap' make[3]: Leaving directory `/app/sdb/gcc-build/x86_64-unknown-linux-gnu/libmudflap' make[2]: Leaving directory `/app/sdb/gcc-build/x86_64-unknown-linux-gnu/libmudflap' make[1]: Leaving directory `/app/sdb/gcc-build'
最終整個編譯目錄佔用了2.7GB空間,消耗的時間在40~50分鐘內
# make install
根據編譯前的設定,在指定目錄生成了對應的gcc文件夾
#ls /usr/local/gcc-4.8.5/ bin include lib lib64 libexec share
查驗版本
#/usr/local/gcc-4.8.5/bin/gcc -dumpversion 4.8.5 #/usr/local/gcc-4.8.5/bin/g++ -dumpversion 4.8.5 #/usr/local/gcc-4.8.5/bin/c++ -dumpversion 4.8.5
須要將新版gcc的庫文件安裝路徑,添加到「庫的搜索路徑」(LD_LIBRARY_PATH)這個環境變量中,前面在make install結束時,系統也給出了相似的提示信息(參考前面的截圖):
臨時生效:
#export LD_LIBRARY_PATH="/usr/local/gcc-4.8.5/lib64:$LD_LIBRARY_PATH"
永久生效:
不建議直接修改ld.so.conf,推薦的作法是在ld.so.conf.d目錄下按程序名創建以.conf結尾的文件,把庫路徑寫入便可。 #echo '/usr/local/gcc-4.8.5/lib64' > /etc/ld.so.conf.d/gcc4.8.5.conf #ldconfig 更新加載動態庫cache 出現如下提示,把這個文件刪除了或忽略它 ldconfig: /usr/local/gcc-4.8.5/lib64/libstdc++.so.6.0.19-gdb.py is not an ELF file - it has the wrong magic bytes at the start. 在我實際使用中,到這一步都已經能夠正常編譯安裝mariadb 10.2.12了。並不須要添加新gcc的環境變量。
#vim /etc/profile.d/env.sh PATH=/usr/local/gcc-4.8.5/bin:$PATH #source /etc/profile.d/env.sh
到這裏,系統會優先根據PATH路徑的前後順序直接加載使用最新版本的gcc工具。已經能夠正常工做了。能夠查看後面的測試章節。
若是是須要gcc多版本共存的狀況,請直接跳至下面的 多版本gcc共存 開始閱讀。
make這種自動編譯大型項目的工具只會使用cc做爲編輯器,而cc則是指向舊的gcc程序,
#make -p|grep "CC =" CC = cc #ll /usr/bin/cc lrwxrwxrwx. 1 root root 3 Jan 27 10:07 /usr/bin/cc -> gcc
如下是網上說的更新某個動態庫,我並無這麼作,也能正常的把mariadb 10.2.12編譯成功。留着備用吧。
這裏的操做未執行: #strings /usr/lib64/libstdc++.so.6 | grep GLIBC 看最後一個,這個與libstdc++.so.6.0.13的尾號是相對應的 GLIBCXX_3.4.13 #ln -sf /usr/local/gcc-4.8.5/lib64/libstdc++.so.6.0.19 /usr/lib64/libstdc++.so.6
至此,前面生成的一些編譯目錄和源碼相關文件均可以按你的須要進行清理了。
有時候因爲各類緣由須要將不一樣版本的gcc編譯器都同時存在系統中,方便進行調用。若是隻是開發單獨在編譯的時候須要的話,僅僅將對應版本路徑直接執行就能夠了,我的單獨配置LD_LIBRARY_PATH。
當是以系統級別總體切換的時候,那就須要用到一個小工具了。
alternatives是dpkg的實用工具,用來維護系統命令的符號連接,以決定系統默認使用什麼命令。
使用此工具管理命令時,必需要配置環境變量的PATH路徑。如:/usr/local/gcc-4.8.5/bin
alternatives [options] --install link name path priority [--slave link name path]... [--initscript service] alternatives [options] --remove name path alternatives [options] --set name path alternatives [options] --auto name alternatives [options] --display name alternatives [options] --config name 具體用法,請man #ll /usr/sbin/update-alternatives lrwxrwxrwx. 1 root root 12 Dec 13 20:15 /usr/sbin/update-alternatives -> alternatives
語法說明:
#gcc -v gcc version 4.4.7 20120313 (Red Hat 4.4.7-18) (GCC)
#mv /usr/bin/gcc /usr/bin/gcc-4.4.7 #mv /usr/bin/g++ /usr/bin/g++-4.4.7 #mv /usr/bin/c++ /usr/bin/c++-4.4.7
#alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.4.7 50 #alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.4.7 50 #alternatives --install /usr/bin/c++ c++ /usr/bin/c++-4.4.7 50
#alternatives --install /usr/bin/gcc gcc /usr/local/gcc-4.8.5/bin/gcc 60 #alternatives --install /usr/bin/g++ g++ /usr/local/gcc-4.8.5/bin/g++ 60 #alternatives --install /usr/bin/c++ c++ /usr/local/gcc-4.8.5/bin/c++ 60
#alternatives --display gcc #gcc就是上面定義的名稱 gcc - status is auto. #當前使用的模式 link currently points to /usr/local/gcc-4.8.5/bin/gcc #當前使用的連接 /usr/bin/gcc-4.4.7 - priority 50 #版本1的連接 /usr/local/gcc-4.8.5/bin/gcc - priority 60 #版本2的連接 Current `best' version is /usr/local/gcc-4.8.5/bin/gcc. #優先級高的選項
自動切換配合--auto動做,並設置好優先級數字,數字越大,優先級越高。手動方式切換後,將會取消自動切換。
從手動切換回自動,alternatives --auto gcc
#alternatives --config gcc There are 2 programs which provide 'gcc'. Selection Command ----------------------------------------------- *+ 1 /usr/bin/gcc-4.4.7 2 /usr/local/gcc-4.8.5/bin/gcc Enter to keep the current selection[+], or type selection number: 2 --- #alternatives --config g++ There are 2 programs which provide 'g++'. Selection Command ----------------------------------------------- *+ 1 /usr/bin/g++-4.4.7 2 /usr/local/gcc-4.8.5/bin/g++ Enter to keep the current selection[+], or type selection number: 2 --- #alternatives --config c++ There are 2 programs which provide 'c++'. Selection Command ----------------------------------------------- *+ 1 /usr/bin/c++-4.4.7 2 /usr/local/gcc-4.8.5/bin/c++ Enter to keep the current selection[+], or type selection number: 2
#gcc -dumpversion 4.8.5 #g++ -dumpversion 4.8.5 #c++ -dumpversion 4.8.5
這是使用系統舊版本4.4.7 gcc編譯cmake時的提示,而且報錯退出。
#../cmake-3.10.2/configure --prefix=/usr/local/cmake-3.10.2 --------------------------------------------- CMake 3.10.2, Copyright 2000-2017 Kitware, Inc. and Contributors Found GNU toolchain C compiler on this system is: gcc --------------------------------------------- Error when bootstrapping CMake: Cannot find a C++ compiler supporting C++11 on this system. Please specify one using environment variable CXX. See cmake_bootstrap.log for compilers attempted.
這是使用新版本4.8.5 gcc編譯cmake時的提示,已經沒有報錯了
#../cmake-3.10.2/configure --prefix=/usr/local/cmake-3.10.2 --------------------------------------------- CMake 3.10.2, Copyright 2000-2017 Kitware, Inc. and Contributors Found GNU toolchain C compiler on this system is: gcc C++ compiler on this system is: g++ -std=gnu++1y Makefile processor on this system is: gmake g++ has setenv g++ has unsetenv g++ does not have environ in stdlib.h g++ has stl wstring g++ has <ext/stdio_filebuf.h>
編譯MariaDB 10.2.12,由於這個版本明確指名須要使用gcc 的 c++11特性 能夠明確的看到版本號而且調用成功 -- Running cmake version 3.10.2 -- The C compiler identification is GNU 4.8.5 -- The CXX compiler identification is GNU 4.8.5 -- Check for working C compiler: /usr/bin/gcc -- Check for working C compiler: /usr/bin/gcc -- works -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Detecting C compile features -- Detecting C compile features - done -- Check for working CXX compiler: /usr/bin/c++ -- Check for working CXX compiler: /usr/bin/c++ -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Detecting CXX compile features -- Detecting CXX compile features - done -- Looking for SHM_HUGETLB -- Looking for SHM_HUGETLB - found -- MariaDB 10.2.12