<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>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ## 21.3 用 make 進行宏編譯 在本章一開始我們提到過 make 的功能是可以簡化編譯過程里面所下達的指令,同時還具有很多很方便的功能!那么下面咱們就來試看看使用 make 簡化下達編譯指令的流程吧! ### 21.3.1 為什么要用 make 先來想像一個案例,假設我的可執行文件里面包含了四個源代碼文件,分別是 main.c haha.c sin_value.c cos_value.c 這四個文件,這四個文件的目的是: * main.c :主要的目的是讓使用者輸入角度數據與調用其他三支副程序; * haha.c :輸出一堆有的沒有的訊息而已; * sin_value.c :計算使用者輸入的角度(360) sin 數值; * cos_value.c :計算使用者輸入的角度(360) cos 數值。 這四個文件你可以到 [http://linux.vbird.org/linux_basic/0520source/main.tgz](http://linux.vbird.org/linux_basic/0520source/main.tgz) 來下載。由于這四個文件里面包含了相關性,并且還用到數學函數在里面,所以如果你想要讓這個程序可以跑, 那么就需要這樣編譯: ``` # 1\. 先進行目標文件的編譯,最終會有四個 *.o 的文件名出現: [root@study ~]# gcc -c main.c [root@study ~]# gcc -c haha.c [root@study ~]# gcc -c sin_value.c [root@study ~]# gcc -c cos_value.c # 2\. 再進行鏈接成為可執行文件,并加入 libm 的數學函數,以產生 main 可執行文件: [root@study ~]# gcc -o main main.o haha.o sin_value.o cos_value.o -lm # 3\. 本程序的執行結果,必須輸入姓名、360 度角的角度值來計算: [root@study ~]# ./main Please input your name: VBird &lt;==這里先輸入名字 Please enter the degree angle (ex&gt; 90): 30 &lt;==輸入以 360 度角為主的角度 Hi, Dear VBird, nice to meet you. &lt;==這三行為輸出的結果喔! The Sin is: 0.50 The Cos is: 0.87 ``` 編譯的過程需要進行好多動作啊!而且如果要重新編譯,則上述的流程得要重新來一遍,光是找出這些指令就夠煩人的了! 如果可以的話,能不能一個步驟就給他完成上面所有的動作呢?那就利用 make 這個工具吧! 先試看看在這個目錄下創建一個名為 makefile 的文件,內容如下: ``` # 1\. 先編輯 makefile 這個規則檔,內容只要作出 main 這個可執行文件 [root@study ~]# vim makefile main: main.o haha.o sin_value.o cos_value.o gcc -o main main.o haha.o sin_value.o cos_value.o -lm # 注意:第二行的 gcc 之前是 &lt;tab&gt; 按鍵產生的空格喔! # 2\. 嘗試使用 makefile 制訂的規則進行編譯的行為: [root@study ~]# rm -f main *.o &lt;==先將之前的目標文件去除 [root@study ~]# make cc -c -o main.o main.c cc -c -o haha.o haha.c cc -c -o sin_value.o sin_value.c cc -c -o cos_value.o cos_value.c gcc -o main main.o haha.o sin_value.o cos_value.o -lm # 此時 make 會去讀取 makefile 的內容,并根據內容直接去給他編譯相關的文件啰! # 3\. 在不刪除任何文件的情況下,重新執行一次編譯的動作: [root@study ~]# make make: `main' is up to date. # 看到了吧!是否很方便呢!只會進行更新 (update) 的動作而已。 ``` 或許你會說:“如果我創建一個 shell script 來將上面的所有動作都集結在一起,不是具有同樣的效果嗎?”呵呵! 效果當然不一樣,以上面的測試為例,我們僅寫出 main 需要的目標文件,結果 make 會主動的去判斷每個目標文件相關的源代碼文件,并直接予以編譯,最后再直接進行鏈接的動作! 真的是很方便啊!此外,如果我們更動過某些源代碼文件,則 make 也可以主動的判斷哪一個源代碼與相關的目標文件文件有更新過, 并僅更新該文件,如此一來,將可大大的節省很多編譯的時間呢!要知道,某些程序在進行編譯的行為時,會消耗很多的 CPU 資源呢!所以說, make 有這些好處: * 簡化編譯時所需要下達的指令; * 若在編譯完成之后,修改了某個源代碼文件,則 make 僅會針對被修改了的文件進行編譯,其他的 object file 不會被更動; * 最后可以依照相依性來更新 (update) 可執行文件。 既然 make 有這么多的優點,那么我們當然就得好好的了解一下 make 這個令人關心的家伙啦!而 make 里面最需要注意的大概就是那個規則文件,也就是 makefile 這個文件的語法啦!所以下面我們就針對 makefile 的語法來加以介紹啰。 ### 21.3.2 makefile 的基本語法與變量 make 的語法可是相當的多而復雜的,有興趣的話可以到 GNU [[1]](#ps1) 去查閱相關的說明,鳥哥這里僅列出一些基本的規則,重點在于讓讀者們未來在接觸源代碼時,不會太緊張啊! 好了,基本的 makefile 規則是這樣的: ``` 標的(target): 目標文件1 目標文件2 &lt;tab&gt; gcc -o 欲創建的可執行文件 目標文件1 目標文件2 ``` 那個標的 (target) 就是我們想要創建的信息,而目標文件就是具有相關性的 object files ,那創建可執行文件的語法就是以 &lt;tab&gt; 按鍵開頭的那一行!特別給他留意喔,“命令列必須要以 tab 按鍵作為開頭”才行!他的規則基本上是這樣的: * 在 makefile 當中的 # 代表注解; * &lt;tab&gt; 需要在命令行 (例如 gcc 這個編譯器指令) 的第一個字符; * 標的 (target) 與相依文件(就是目標文件)之間需以“:”隔開。 同樣的,我們以剛剛上一個小節的范例進一步說明,如果我想要有兩個以上的執行動作時, 例如下達一個指令就直接清除掉所有的目標文件與可執行文件,該如何制作呢? ``` # 1\. 先編輯 makefile 來創建新的規則,此規則的標的名稱為 clean : [root@study ~]# vi makefile main: main.o haha.o sin_value.o cos_value.o gcc -o main main.o haha.o sin_value.o cos_value.o -lm clean: rm -f main main.o haha.o sin_value.o cos_value.o # 2\. 以新的標的 (clean) 測試看看執行 make 的結果: [root@study ~]# make clean &lt;==就是這里!通過 make 以 clean 為標的 rm -rf main main.o haha.o sin_value.o cos_value.o ``` 如此一來,我們的 makefile 里面就具有至少兩個標的,分別是 main 與 clean ,如果我們想要創建 main 的話,輸入“make main”,如果想要清除有的沒的,輸入“make clean”即可啊!而如果想要先清除目標文件再編譯 main 這個程序的話,就可以這樣輸入:“make clean main”,如下所示: ``` [root@study ~]# make clean main rm -rf main main.o haha.o sin_value.o cos_value.o cc -c -o main.o main.c cc -c -o haha.o haha.c cc -c -o sin_value.o sin_value.c cc -c -o cos_value.o cos_value.c gcc -o main main.o haha.o sin_value.o cos_value.o -lm ``` 這樣就很清楚了吧!但是,你是否會覺得,咦! makefile 里面怎么重復的數據這么多啊!沒錯!所以我們可以再借由 shell script 那時學到的“變量”來更簡化 makefile 喔: ``` [root@study ~]# vi makefile LIBS = -lm OBJS = main.o haha.o sin_value.o cos_value.o main: ${OBJS} gcc -o main ${OBJS} ${LIBS} clean: rm -f main ${OBJS} ``` 與 [bash shell script](../Text/index.html) 的語法有點不太相同,變量的基本語法為: 1. 變量與變量內容以“=”隔開,同時兩邊可以具有空格; 2. 變量左邊不可以有 &lt;tab&gt; ,例如上面范例的第一行 LIBS 左邊不可以是 &lt;tab&gt;; 3. 變量與變量內容在“=”兩邊不能具有“:”; 4. 在習慣上,變量最好是以“大寫字母”為主; 5. 運用變量時,以 ${變量} 或 $(變量) 使用; 6. 在該 shell 的環境變量是可以被套用的,例如提到的 CFLAGS 這個變量! 7. 在命令行界面也可以給予變量。 由于 gcc 在進行編譯的行為時,會主動的去讀取 CFLAGS 這個環境變量,所以,你可以直接在 shell 定義出這個環境變量,也可以在 makefile 文件里面去定義,更可以在命令行當中給予這個咚咚呢!例如: ``` [root@study ~]# CFLAGS="-Wall" make clean main # 這個動作在上 make 進行編譯時,會去取用 CFLAGS 的變量內容! ``` 也可以這樣: ``` [root@study ~]# vi makefile LIBS = -lm OBJS = main.o haha.o sin_value.o cos_value.o CFLAGS = -Wall main: ${OBJS} gcc -o main ${OBJS} ${LIBS} clean: rm -f main ${OBJS} ``` 咦!我可以利用命令行進行環境變量的輸入,也可以在文件內直接指定環境變量,那萬一這個 CFLAGS 的內容在命令行與 makefile 里面并不相同時,以那個方式輸入的為主?呵呵!問了個好問題啊! 環境變量取用的規則是這樣的: 1. make 命令行后面加上的環境變量為優先; 2. makefile 里面指定的環境變量第二; 3. shell 原本具有的環境變量第三。 此外,還有一些特殊的變量需要了解的喔: * $@:代表目前的標的(target) 所以我也可以將 makefile 改成: ``` [root@study ~]# vi makefile LIBS = -lm OBJS = main.o haha.o sin_value.o cos_value.o CFLAGS = -Wall main: ${OBJS} gcc -o $@ ${OBJS} ${LIBS} &lt;==那個 $@ 就是 main ! clean: rm -f main ${OBJS} ``` 這樣是否稍微了解了 makefile (也可能是 Makefile) 的基本語法?這對于你未來自行修改源代碼的編譯規則時,是很有幫助的喔!^_^!
                  <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>

                              哎呀哎呀视频在线观看