<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] # 更新gcc 紅帽其實已經編譯好了高版本的gcc,但未更新到base和epel這兩個常用的源中,而是放在`scl`中。第一步便是安裝`scl`: ~~~ yum install -y centos-release-scl glibc-static ~~~ 如果你之前用過`grouplist/install`等命令,應該知道gcc包含在`Development Tools`這個組中。那么`scl`中的gcc/g++軟件包的前綴都是`devtoolset`,也就不難理解了。安裝gcc 6版本的命令是: ~~~ yum install -y devtoolset-8-gcc devtoolset-8-gcc-c++ ~~~ `devtoolset-6`中的gcc版本為gcc 6,除此之外還有如下版本: * devtoolset-3: gcc 4.9 * devtoolset-4: gcc 5 * devtoolset-6: gcc 6 * devtoolset-7: gcc 7 * devtoolset-8: gcc 8 至于為什么沒有devtoolset-5,我也不清楚,估計是包含在devtoolset-4中了吧。值得說明的是這些軟件包可以同時安裝,不會相互覆蓋和沖突,也不會覆蓋系統的版本。即可以在系統中同時安裝gcc 6, gcc 7, gcc 8等多個版本。 因為不會覆蓋系統默認的gcc,使用這些軟件的方法有四種: 1. 使用絕對路徑; 2. 添加可執行文件路徑到PATH環境變量; 3. 使用官方推薦的加載命令:`scl enable devtoolset-x bash`, x為要啟用的版本; 4. 執行安裝軟件自帶的腳本: `source /opt/rh/devtoolset-x/enable`,x為要啟用的版本。 推薦使用最后兩種方式,例如啟用gcc 6: `source /opt/rh/devtoolset-6/enable`,然后輸入`gcc -v`查看版本已經變成gcc 6.3.1。使用類似的命令可以隨時在多個gcc版本中切換。如果希望長期使用高版本,可將此命令寫入`.bashrc`等配置文件。 ~~~ echo "source /opt/rh/devtoolset-8/enable" >>/etc/profile ~~~ 最后說一下,scl以及scl-rh源中的軟件包都安裝在/opt/rh/目錄下,包含可執行文件、配置等。所以啟用命令的路徑是`/opt/rh/xxx/enable`,安裝的服務重啟命令則可能是`systemctl restart rh-xxx`,需要加rh或scl前綴以區別其他源的包。如果你用過remi/gitlab等源,其行為方式也是類似的。 # 工作流 gcc編譯器從拿到一個c源文件到生成一個可執行程序,中間一共經歷了四個步驟: ![](https://img.kancloud.cn/4b/55/4b55bf2a87b293f319405e06623affff_805x126.png) 四個步驟并不是gcc獨立完成的,而是在內部調用了其他工具,從而完成了整個工作流程: ![](https://img.kancloud.cn/43/d4/43d4edb301b4f8400db1487e4b45a02b_772x208.png) gcc工作的流程 > deng@itcast:~/share/3rd/1gcc$ ls 1hello.c > > 第一步: 進行預處理 > > deng@itcast:~/share/3rd/1gcc$ gcc -E 1hello.c -o 1hello.i > > 第二步: 生成匯編文件 > > deng@itcast:~/share/3rd/1gcc$ gcc -S 1hello.i -o 1hello.s > > 第三步: 生成目標代碼 > > deng@itcast:~/share/3rd/1gcc$ gcc -c 1hello.s -o 1hello.o > > 第四步: 生成可以執行文件 > > deng@itcast:~/share/3rd/1gcc$ gcc 1hello.o -o 1hello 第五步: 執行 deng@itcast:~/share/3rd/1gcc?$ ./1hello hello itcast 直接將源文件生成一個可以執行文件 > deng@itcast:~/share/3rd/1gcc$ gcc 1hello.c -o 1hello deng@itcast:~/share/3rd/1gcc?$ ./1hello hello itcast 如果不指定輸出文件名字, gcc編譯器會生成一個默認的可以執行a.out > deng@itcast:~/share/3rd/1gcc$ gcc 1hello.c > deng@itcast:~/share/3rd/1gcc?$ ls 1hello 1hello.c 1hello.i 1hello.o 1hello.s a.out deng@itcast:~/share/3rd/1gcc?$ ./a.out > hello itcast # 常用選項 | **選項** | **作用** | | --- | --- | | \-o file | 指定生成的輸出文件名為file | | \-E | 只進行預處理 | | \-S(大寫) | 只進行預處理和編譯 | | \-c(小寫) | 只進行預處理、編譯和匯編 | | \-v / --version | 查看gcc版本號 | | \-g | 包含調試信息 | | \-On n=0~3 | 編譯優化,n越大優化得越多 | | \-Wall | 提示更多警告信息 | | \-D | 編譯時定義宏 | 顯示所有的警告信息 > gcc -Wall test.c 將警告信息當做錯誤處理 > gcc -Wall -Werror test.c 測試程序(-D選項): ~~~ #include <stdio.h> ? int main(void) { printf("SIZE: %d\n", SIZE); return 0; } ~~~ ~~~ deng@itcast:~/test$ gcc 2test.c -DSIZE=10 deng@itcast:~/test$ ./a.out SIZE: 10 ~~~ # 靜態鏈接和動態鏈接 鏈接分為兩種:**靜態鏈接**、**動態鏈接**。 **靜態、動態編譯對比** 前面我們編寫的應用程序大量用到了標準庫函數,系統默認采用動態鏈接的方式進行編譯程序,若想采用靜態編譯,加入-static參數。 以下是分別采用動態編譯、靜態編譯時文件對比: 測試程序(test.c)如下: ~~~ #include <stdio.h> int main(void) { printf("hello world \n"); return 0; } ~~~ 編譯: > deng@itcast:~/test$ gcc test.c -o test\_share > > deng@itcast:~/test$ gcc -static test.c -o test\_static # 靜態庫和動態庫 所謂“程序庫”,簡單說,就是包含了數據和執行碼的文件。其不能單獨執行,可以作為其它執行程序的一部分來完成某些功能。 庫的存在可以使得程序模塊化,可以加快程序的再編譯,可以實現代碼重用,可以使得程序便于升級。 程序庫可分**靜態庫(static library)**和**共享庫(shared library)** ## 靜態庫制作 靜態庫可以認為是一些目標代碼的集合,是在可執行程序運行前就已經加入到執行碼中,成為執行程序的一部分。 按照習慣,一般以“.a”做為文件后綴名。靜態庫的命名一般分為三個部分: * 前綴:lib * 庫名稱:自己定義即可 * 后綴:.a 所以最終的靜態庫的名字應該為:**libxxx.a** ![](https://img.kancloud.cn/ee/81/ee816bcc97df817ccafbf5a4adff0d5f_546x341.png) 步驟1:將c源文件生成對應的.o文件 > deng@itcast:~/test/3static\_lib$ gcc -c add.c -o add.o > deng@itcast:~/test/3static\_lib?$ gcc -c sub.c -o sub.o > deng@itcast:~/test/3static\_lib?$ gcc -c mul.c -o mul.o > deng@itcast:~/test/3static\_lib?$ gcc -c div.c -o div.o 步驟2:使用打包工具ar將準備好的.o文件打包為.a文件 libtest.a > deng@itcast: ar -rcs libtest.a add.o sub.o mul.o div.o **在使用ar工具是時候需要添加參數:rcs** * r更新 * c創建 * s建立索引 **靜態庫使用** 靜態庫制作完成之后,需要將.a文件和頭文件一起發布給用戶。 假設測試文件為main.c,靜態庫文件為libtest.a頭文件為head.h 編譯命令: > deng@itcast: gcc test.c -L./ -I./ -ltest -o test 參數說明: * \-L:表示要連接的庫所在目錄 * \-I./: I(大寫i) 表示指定頭文件的目錄為當前目錄 * \-l(小寫L):**指定鏈接時需要的庫,去掉前綴和后綴** ![](https://img.kancloud.cn/cc/ef/cceff1734d1092b9c5b3278721acbded_401x318.png) add.h ~~~ #ifndef __ADD_H__ #define __ADD_H__ int add(int x, int y); #endif /* __ADD_H__ */ ~~~ add.c ~~~ #include "add.h" int add(int x, int y) { return x + y; } ~~~ test.c ~~~ #include <stdio.h> #include "add.h" int main(void) { printf("1 + 2 = %d\n", add(1, 2)); return 0; } ~~~ ## 動態庫制作 共享庫在程序編譯時并不會被連接到目標代碼中,而是在程序運行是才被載入。不同的應用程序如果調用相同的庫,那么在內存里只需要有一份該共享庫的實例,規避了空間浪費問題。 動態庫在程序運行是才被載入,也解決了靜態庫對程序的更新、部署和發布頁會帶來麻煩。用戶只需要更新動態庫即可,增量更新。 按照習慣,一般以“.so”做為文件后綴名。共享庫的命名一般分為三個部分: * 前綴:lib * 庫名稱:自己定義即可 * 后綴:.so 所以最終的動態庫的名字應該為:`libxxx.so` ![](https://img.kancloud.cn/53/f3/53f3cc74abc78768f1d109cd7209e390_402x326.png) **1)動態庫制作** 步驟一:生成目標文件,此時要加編譯選項:-fPIC(fpic) > deng@itcast:~/test/5share\_lib$ gcc -fPIC -c add.c > deng@itcast:~/test/5share\_lib?$ gcc -fPIC -c sub.c > deng@itcast:~/test/5share\_lib$ gcc -fPIC -c mul.c > deng@itcast:~/test/5share\_lib?$ gcc -fPIC -c div.c 參數:-fPIC 創建與地址無關的編譯程序(pic,position independent code),是為了能夠在多個應用程序間共享。 步驟二:生成共享庫,此時要加鏈接器選項: -shared(指定生成動態鏈接庫) > deng@itcast:~/test/5share\_lib$ gcc -shared add.o sub.o mul.o div.o -o libtest.so 步驟三: 通過nm命令查看對應的函數 > deng@itcast: nm libtest.so | grep add > deng@itcast: nm libtest.so | grep sub ldd查看可執行文件的依賴的動態庫 > deng@itcast:~/share/3rd/2share\_test$ ldd test > linux-vdso.so.1 => (0x00007ffcf89d4000) libtest.so => /lib/libtest.so (0x00007f81b5612000) libc.so.6 => /lib/x86\_64-linux-gnu/libc.so.6 (0x00007f81b5248000) /lib64/ld-linux-x86-64.so.2 (0x00005562d0cff000) **2)動態庫測試** 引用動態庫編譯成可執行文件(跟靜態庫方式一樣) > deng@itcast:~/test/6share\_test$ gcc test.c -L. -I. -ltest (-I. 大寫i -ltest 小寫L) 然后運行:./a.out,發現竟然報錯了!!! ![](https://img.kancloud.cn/d4/d8/d4d83aed86419bca70cb55413b55dbdf_792x154.png) * 當系統加載可執行代碼時候,能夠知道其所依賴的庫的名字,但是還需要知道絕對路徑。此時就需要系統動態載入器(dynamic linker/loader)。 * 對于elf格式的可執行程序,是由`ld-linux.so`來完成的,它先后搜索elf文件的 DT\_RPATH段 — 環境變量LD\_LIBRARY\_PATH — /etc/ld.so.cache文件列表 —**/lib/, /usr/lib**目錄找到庫文件后將其載入內存。 **3)如何讓系統找到動態庫** * 拷貝自己制作的共享庫到/lib或者/usr/lib(不能是/lib64目錄) * 臨時設置LD\_LIBRARY\_PATH: > export LD\_LIBRARY\_PATH=$LD\_LIBRARY\_PATH:庫路徑 * 永久設置,把export LD\_LIBRARY\_PATH=$LD\_LIBRARY\_PATH:庫路徑,設置到~/.bashrc或者 /etc/profile文件中 > deng@itcast:~/share/3rd/2share\_test$ vim ~/.bashrc > > 最后一行添加如下內容: > > export LD\_LIBRARY\_PATH=$LD\_LIBRARY\_PATH:/home/deng/share/3rd/2share\_test 使環境變量生效 > deng@itcast: source ~/.bashrc > deng@itcast: ./test > a + b = 20 a - b = 10 * 將其添加到 /etc/ld.so.conf文件中 編輯/etc/ld.so.conf文件,加入庫文件所在目錄的路徑 運行sudo ldconfig -v,該命令會重建/etc/ld.so.cache文件 > deng@itcast: sudo vim /etc/ld.so.conf > > 文件最后添加動態庫路徑(絕對路徑) ![](https://img.kancloud.cn/90/a8/90a8f53e52a97ac48099a627062e32bb_496x143.png) * > 使生效 > deng@itcast: sudo ldconfig -v 或者使用符號鏈接, 但是一定要使用絕對路徑 > deng@itcast: sudo ln -s /home/deng/test/6share\_test/libtest.so /lib/libtest.so
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看