【學習記錄】關於makefile而進行的互連網學習技巧練習及學習筆記和學習心得記錄(vs2010)

來源:互聯網
上載者:User

標籤:

我也不知道作為一個完全的windows平台下的不怎麼專業的軟體工程學生,看到《Accelerated C++》的原始碼,第一反應是:哦!我應該用make產生工程檔案。然後我愉快的用AOL開始搜尋相關資料。

然並卵!我一定是被什麼奇怪的生物附身了。我應該直接用vs建立項目->匯入檔案。然後……ctrl+F5。多麼完美。

可是……以下:

 

【教程】來自於雲風大大的blog(雲風的 BLOG)

IDE 不是程式員的唯一選擇(一)

以及後面的(二)(三)(四)

 

以及大大寫了一篇半,只為了說明用cl來編譯和連結程式的步驟做引出make工具的引子。我……【手動面無表情

其實我猜想應該是大大突發奇想寫一篇如何用cl命令來編譯器,給那些好奇心重,不按常理出牌,然並卵並沒有很屌的學習能力的新手一些引導。然後……就一發不可收拾了。所以才會有這麼詭異的篇幅結構?好吧我承認這隻是我的腦補,最近越來越覺得做程式員好寂寞的,機器不會跟我說話。每次它跟我說話的時候就是My Code有問題的時候了><,以及我確實是已經點亮在無聊環境下可以靠著哼歌和自我腦補完美調節心情的技能。當然以上都是廢話。

 

相關錯誤以及修正方法在後續文章中說明。下面,let‘s jump.噢,入了奇怪的戲,下面是我的學習記錄。

 

【part.1】vs2010內建的cl進行編譯連結工作以及路徑設定和問題解決

步驟記錄:

命令列(win+R,輸入cmd空格召喚)模式下,輸入

cl foo.c

系統會產生foo.obj,foo.exe兩個檔案,編譯原理的老師說,程式產生是先編譯,再連結的過程。如果沒記錯編譯是產生中間代碼形式,貌似是彙編?然後再連結產生二進位程式,也就是exe,executive的縮寫,如果我沒拼錯。嗯。記錯或者拼錯求不打臉QAQ。

雲風大大說,cl這個命令就是給編譯,連結這個過程加個殼,或者我們應該時髦一點說,封裝一下?

嗯,如果提示你任何錯誤,請先檢查你的foo.c是否存在。

以下是錯誤記錄

  1. 輸入cl提示缺少mspdb.dll錯誤。
  2. 輸入命令後提示iostream:缺少檔案支援
  3. 輸入命令後提示無法開啟檔案“kernel32.dll”

相關的解決方案連結在問題上。

當然你可能會因為然並卵我的室友在玩遊戲/用迅雷我的網速是豆腐渣並不想跳轉,當然也許你跳轉了之後發現太長不看。好吧,下面是……我的解決方案。

  1. 雲風大大的解決方案是運行:VS安裝目錄/Common7\Tools\vsvars32.bat(或者vsvarsll.bat)  指令碼,會設定vs運行需要的環境變數。我用的是在環境變數path中加入: VS安裝目錄\Common7\IDE。(環境變數使用 我的電腦(右鍵)-> 屬性 -> 進階系統設定 ->環境變數 開啟)
  2. 環境變數總建立LIB和INCLUDE變數,(LIB)C:/Program Files/Microsoft SDKs/Windows/v6.0A/Lib;C:/Program Files/Microsoft SDKs/Windows/v5.0/Lib;VS安裝目錄/VC/lib    (INCLUDE)VS安裝目錄/VC/include(說好的vsvarsall.bat解決所有問題呢!!!)
  3. 將  C:\Program Files\Microsoft SDKs\Windows\v7.0A\Lib  目錄下的  kernel32.lib  拷貝到  VS安裝目錄\VC\lib目錄 下。
cl foo.c bar.c // 多檔案連結產生,預設產生EXE名稱為第一個源檔案名稱

  

cl /Fefoobar foo.c bar.c // 產生foobar.exe,/Fe和foobar之間沒有空格。

 

cl /Fefoobar foo.obj bar.objlink /out:foobar.exe foo.obj bar.obj // 二者等價

調試:

cl /Zi foo.c

接下來,雲風將傳授一門關於調試的獨門秘籍。

知道調試器是如何?斷點這個功能的嗎?其實它偷偷的在你的程式要設定斷點的位置放置了一條調試中斷指令。在 x86 32 位系統上,這是一條單位元組指令,彙編代碼是 int 3 。cpu 運行程式的時候,碰到 int 3 就會把控制權交給調試器,當你在調試器中選擇繼續啟動並執行時候,調試器再將被替換的程式機器指令換回去,讓程式繼續運行。

知道了這個細節,我們就可以自己提前設定調試斷點了。我稱它為硬斷點。只要程式運行到,就一定會停下來。如果你想在運行期屏蔽硬斷點,需要在源碼上做一些工作了。

現在在你剛才的 foo.c 的程式入口處加一行 __asm int 3 ( 如果你在用 gcc 可以加 asm ("int $3"); ) 重新用 cl /Zi foo.c 編譯一次。然後在命令列直接運行 foo.exe 。

馬上,你將會看到一個熟悉的關於程式崩潰的對話方塊。沒關係,它是由你插入的硬斷點 (int 3) 造成的。如果你正確安裝了 vs ,vs 應該已經把自己設定成系統預設的調試器了。點對話方塊上的按鈕,便將啟動 vs 的 ide ,我們會發現程式正好停在了 int 3 那行彙編的地方。現在你可以盡情的單步跟蹤了。

http://blog.codingnow.com/2008/09/replacement_of_ide_1.html

其實就是報錯->vs調試,然而vs調試用的並不熟練……。 

 

【part2】make工具

 雲風大大推薦使用MinGW的gmake。關鍵字 MinGW GNU make

編程之道在於,讓機器做機器的事,人專註於人的思考。如果真的靠手鍵入每條編譯指令,無疑讓程式員去做了機器之事。把編譯指令寫入批處理(指令碼)檔案,僅僅只是節省了每次編譯的重複勞動,並沒有從根本上解脫。

在從 C 的原始碼構建最終的執行檔案這個流程中,哪些是人的創造,哪些是機器應行之事?顯而易見,程式員應該做的是:

  1. 教會機器,如何把一個 .c 檔案編譯成 .obj 檔案。

  2. 教會機器,如何把若干個 .obj 檔案連結成 .exe 檔。

  3. 告訴機器,你的項目由那些 .c 檔案構成,最終你想產生一個叫什麼名字的 .exe 檔。

其中前兩步,對於大多數類似的項目來說是共同的,所以我們只用也只應該教機器一次。而第三步,提供一個檔案清單和一個目標檔案名給機器即可。

 編寫makefile

all :// 必須以all開頭    echo Hello World            // 行前必須是一個tab

  

然後gmake,over。

我的gmake預設只執行第一個命令,即只執行echo Hello World。如果要執行後面的foobar.exe,必須使用gmake foobar.exe。

 

上一篇開篇,我們講到了,如何用命令列分開編譯 .c 檔案,並把它們連結起來。這樣做,可以使每次修改都可以讓機器做最少的編譯任務。對於小工程,這樣做的意義不大。但是大工程,可能就能幫我們節約不少時間了。記住這一點,永遠沒有通用的最優方案。因為實施方案本身也是有成本的。我們只需要找到最直接最簡單的方法就可以了。比如項目一開始,可以寫一個最簡單的 Makefile 檔案,隨著項目規模的擴大再逐步完善。

分開編譯再連結這件事,人做起來都比較繁瑣,把它教給機器去做,當然也會更繁瑣。所以我沒有在上一篇中詳解。好學的同學應該會自己弄了,今天,我也來寫寫自己的方案。但在此之前,我們先梳理一下對 Make 的理解。

Make 是一個工作於非常簡單的模式下的工具。它的內部有一張表,記錄了目標檔案之間的依賴關係。Makefile 就是用來描述這張依賴關係表的。對於依賴關係表的描述,用了一種非常簡單的文法:

目標 : 依賴

這表示,"目標" 的構建依賴於 "依賴" 先構建出來。這裡,"目標" 和 "依賴" 都是檔案系統中的檔案,而"依賴"本身也可以是一個"目標"。如果 "依賴" 的檔案時間新於 "目標" 的檔案時間,表示 "目標" 需要重新構建。如果 "目標" 檔案不存在,也會觸發這種構建過程。

一個目標可以有多個依賴,可以在 : 後以空格分開寫上多個,比如:

目標 : 依賴1 依賴2 依賴3

這在我們前一篇中已經多次見過了。其實還有另一個規則,我們可以寫:

目標 : 依賴1

目標 : 依賴2

這樣分兩行寫,即,每次寫 "目標 : 依賴" 都在依賴關係的依賴關係表中添加了一項。(關於同名的依賴添加的問題,以後我們在討論)

舉個例子:

a : b c

a : ba : c

其實是等價的。

每個目標的構建方法並不是由 Make 內建功能完成的,Make 只是簡單調用寫在 "目標" 定義的下一行的若干命令列指令碼而已。而每一行命令列指令碼必須以 Tab 鍵開頭。

注意,如果你把目標的依賴關係分成若干行實現,只可以有一個地方定義構建指令碼。

舉例:

all : aall : ba :    echo [email protected]b :    echo [email protected]

這樣一個 Makefile 用 Make 運行後,會顯示:

echo aaecho bb

為什麼呢?因為 Make 會找 Makefile 中定義的第一個目標,做為它這次的終極目標。在這裡是 all 。all 依賴於 a 和 b 兩個目標。由於你的工作目錄下沒有 a 和 b 兩個檔案,所以觸發了 a 以及 b 的構建。而 a 的構建指令是 echo [email protected] ,[email protected] 指代了當前目標 "a" ,結果就執行了 echo a 。同樣,b 檔案的不存在,導致了 b 的構建,執行了 echo b 。

需要強調的是,echo 並不是 Make 的內建功能。echo 是 Windows 命令列指令(在 *nix 系統上,稱為 shell 指令)。Make 只管忠實的執行那些相關的以 Tab 開始行內描述的命令列指令。目標的構建成功也不以目標檔案是否正確產生為依據。而是以命令執行的結果是否為 0 。記得學 C 語言的時候,老師教你,main 函數得到正確結果時,應該 return 0 吧。這個 main 的 return 0 就是返回給系統用的。Make 通過檢查這個傳回值來覺得命令列指令是否被正確的執行。如果收到非 0 的傳回值,整個 Make 的過程會被中斷。當然,echo 這樣的指令,一般都會返回 0 的。

注意,一個目標是否被正確構建,只取決於構建它的命令列指令是否正確的返回 0 ,而不取決於檔案是否被建立出來或是被更新到最新的時間。在一次構建中,每個目標最多隻會被構建一次。這是由於 Make 只對依賴關係表做一次簡單的拓撲排序,然後就開始工作了。

同樣,我們還可以讓多個目標依賴同樣的東西:

a b : c d

就等價於

a : c db : c d

現在我們可以看到,在 Makefile 裡寫 : 定義,其實就是在填寫一張依賴關係表。每次的一個 : 都向表裡追加一些項目。Make 工作的時候,先讀完整個檔案,把完整的依賴關係表建立好,再根據命令列指定的目標開始工作,如果在命令列不指定目標,預設就是 Makefile 裡寫的第一個目標了。

這樣我們就好理解,除了 Makefile 裡的第一個目標定義之外,所有的依賴關係描述都是無所謂書寫的先後次序的。Make 只管向依賴關係表裡添加表項,不會刪除。原則上也不保證按依賴表中的次序先後來構建,如果你需要一個目標一定先於另一個目標構建,就需要顯式的描述出依賴關係。

 

http://blog.codingnow.com/2008/09/replacement_of_ide_3.html

 

  

 

 【part3】這理應成為一個神作(zuō)

 在我等MinGW下載的時候,突發奇想為什麼不用nmake,然後經過細緻的,仔細地,耐心的看完並沒有幾行的makefile,我覺得我可以嘗試以下輸入:

nmake test

之後,刷刷刷刷刷刷刷刷刷刷刷刷刷刷刷刷,什麼obj,什麼exe都出來了。嗯。我想靜靜。

順帶之前不知道安裝了什麼內建了cygwin……這酸爽。

看完了其實可以參考這個實踐:http://www.cnblogs.com/youngzii/p/3395055.html

 

【學習記錄】關於makefile而進行的互連網學習技巧練習及學習筆記和學習心得記錄(vs2010)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.