看板 C_and_CPP 關於我們 聯絡資訊
零、 前言 可能是學校作業,可能是之前我發過提問文,這星期私信來函不少, 內容從命令列編譯程式碼 到 IDE 環境架構都有, 想說這部份蠻多也曾請求協助於版友,發此文做為回饋, 一次全回答完,也留予往後有需求之人做參考。 我會研究此議題,純粹乃習慣開兩個 IDE 出來,一個是 Project 上之實做; 另一個是 Project 寫到一半時,可能需要什麼小隻的副函式,或其它要驗證東西, 開一個 Visual Studio 就吃很大,所以驗證的 IDE 很少在用 Visual Studio , 甚至嫌 Dev-C++ 還不夠小,最後以 PSPad 進行驗證上之輔助。 由於我使用之 compiler 並不多,僅限於 Visual C++ (CL.exe ) Dev-C++ / MinGW (gcc.exe / g++.exe) 故本文只以此兩套 compiler 做為說明,前文有點煩雜,後文將以 PSPad 輔助, 進行架構小型 IDE。若只對架構小型 IDE 有興趣,而對整體運作沒興趣(或已知), 直接跳到 肆、 使用 PSPad 架構小型 IDE 即可 若對本文有興趣,欲加以實做,建議可下載並安裝 TDM-gcc http://tdm-gcc.tdragon.net/download 我安裝的是 tdm-gcc-4.5.2 (exe), 應是沒附 IDE 版的。 在說明上盡量以 Dev-C++ 4.9.9.2 之環境為說明條件。 可能有書有教,但我是看 spec try 出來的,有不錯的書歡迎推薦。 壹、 Dev-C++ 從 hello.c 到 hello.exe 假設原始碼為 hello.c,為方便解說,放到 D:\ , 絕對路徑為 D:\hello.c 基本上,只要看到 ???? 器,它「應該」就要是一個執行檔。 這裡只是小提一下,一般從 source code (.c) 一路到產生可執行之執行檔 (.exe), 大致有四個步驟,以下命令,請先按下 開始->執行(或按 WinKey+R),輸入cmd.exe 跳出黑黑像 dos 視窗的命令提示字元後才進行操作, 下述之 綠體字 部份,即為要在該黑黑的 dos 視窗(它就叫命令提示字元)裡輸入之指令。 a. 預處理器 (pre-prossor,或稱前編譯 < hello.c to hello.i> ) 將程式碼 (hello.c) 裡,對於 # 註解部份 做處理。 如 #define 展開、#include 插入、(#if、 #ifdef、#endif) 做條件編譯處理。 dev-c++ Z:\> C:\Dev-cpp\bin\cpp.exe "D:\hello.c" "D:\hello.i" ※ 結果在 D:\ 生成 hello.i b. 編譯器 (compiler <hello.i to hello.s> ) 將剛剛預處理完之 .i 吃進來,編譯成低階組合語言。asm code 副檔名非一定, Dev-C++/gcc 為 .c , vs 為 .asm dev-c++ Z:\> C:\Dev-Cpp\libexec\gcc\mingw32\3.4.2\cc1.exe "D:\hello.c" -o "D:\hello.s" ※ 結果在 D:\ 生成 hello.s 注意,上面的 cc1.exe ,最後那個是數字 1 (one),非小寫英文 L。 c. 組譯器 (assembler <hello.s to hello.o> ) 將 .s 組合語言組譯成目的檔 .o,目的檔副檔名在 dev-c++/ gcc 為 .o , vs 為 .obj dev-c++ Z:\> C:\Dev-Cpp\bin\as.exe "D:\hello.s" -o "D:\hello.o" ※ 結果在 D:\ 生成 hello.o d. 連結器 ( linker < hello.o + *.o to hello.exe > ) 這是最後一步驟,將剛剛出來的 .o 再連結成 .exe 執行檔出來, 但這個步驟實在是 太讓人覺得麻煩,我也沒弄得很清楚到底要連哪些 .o 出來,實際上是調用 C:\Dev-Cpp\bin\ld.exe ,此處只好調用 gcc.exe dev-c++ Z:\> C:\Dev-Cpp\bin\gcc.exe D:\hello.o -o D:\hello.exe ※ 結果在 D:\ 生成 hello.exe 事實上真正將 .o 轉到 .exe 的是 ld.exe 連結器 (linker),並非 gcc.exe, 有興趣的話可以詳閱 ld.exe 參數說明,光是一個 hello.exe 要轉過去, 至少要含五、六個 library 裡面,已組譯好的 .o ,這些 .o 目的檔, 大多在 C:\Dev-Cpp\lib 、 C:\Dev-Cpp\lib\gcc\mingw32\3.4.2 裡面 關於 linker 部份,可參考 james732 版大文章 #1DgrW4a5 (C_and_CPP) 這篇寫得很讚。 貮、 談整合性程式 For Dev-C++ / MinGW 如上所見,光是輸出一個 "Hello, World!!" 就這麼麻煩 (1) 先從 hello.c 到 hello.i, pre-processor, cpp.exe (2) 再從 hello.i 到 hello.s, compiler, cc1.exe (3) 接著 hello.s 到 hello.o, assembler, as.exe (4) hello.o + (*.o) 到 hello.exe, linker, ld.exe 這不論是 Dev-C++ 或是 Visual Studio 、 Broland C,即使 Turbo C 也必須這麼做。 但各家發展這些時,都會有大多再開發一隻屬整合這四個程式之另一支程式出來, 如 gcc.exe 便為如此,使用它,甚至可跳過很多步驟,直接從 .c 產生出 .exe 出來 Z:\> C:\Dev-cpp\bin\gcc.exe -o D:\hello.exe D:\hello.c 如果不只一個 .c ,有其它的 .h 等之類的話 Z:\> C:\Dev-cpp\bin\gcc.exe -o D:\hello.exe D:\hello.c D:\h1.h D:\h2.h D:\h1.c D:\h2.c 這些可容易產生,甚至要叫 asm code 出來也可 Z:\> C:\Dev-cpp\bin\gcc.exe -S D:\hello.c 其它的功能不少,點到為止。 For Visual C++ Visual C++ 算是我見過較為例外的,整個從 .c 到 .exe,除了有一個 Linker.exe 是做 連結動作,其它全部功能都塞到 CL.exe 裡面去。但若要用 CL.exe 之前,在命令提示字 元下必須先呼叫 vsvars32.bat 進行環境變數設定 Z:\> call "%VS100COMNTOOLS%vsvars32.bat" For Visual C++ 2010 Z:\> call "VS90COMNTOOLS%vsvars32.bat" For Visual C++ 2008 接下來才可進行 CL.exe 上之使用 產生 hello.exe, hello.obj Z:\> CL.exe Fe"D:\hello.exe" D:\hello.c 產生 hello.exe, hello.obj, hello.asm Z:\> CL.exe Fe"D:\hello.exe" D:\hello.c /FAs 也可進行多個 .c/.h 進行編譯。 參、 MinGW 與 Dev-C++ MinGW 我認為環境架構上一直不是那麼友善,於是如版友之建議,下載了 tdm-gcc-4.5.2 這套下來用 (網址在最一開始地方有附),它和上面說的 Dev-C++ 所使用編譯方式、使用 之 exe、語法,並無顯著差異,唯只有路徑上不一樣,如我手邊安裝完後, gcc.exe 是 位於 C:\MinGW32\bin 底下,故上述所有之 C:\Dev-cpp\bin 全都改成 C:\MinGW32\bin 即可,甚至可以設置 path 之環境變數,這樣下來也不用每次都以絕對位置方式做呼叫。 肆、 使用 PSPad 架構小型 IDE 這方法是有缺點的,要改善的話看 陸、 PSPad 多檔編譯 類似的軟體不只 PSPad,之前還碰過 UltraEdit、NotePad++, 選用 PSPad 之原因在於它免費,同時還類似有 函式導覽、專案管理 等功能, 有興趣的話可再摸摸其他類似之軟體。 PSPad 要下載對版本才好用,確保開始後,設定->語法高亮設定 是看得到的。 若要用 PSPad 去當編輯器,以 Dev-C++ 之 gcc.exe 為 compiler,設定如下 (1) 點擊 設定-> 語法高亮設定 (2) 程式語言選到 C/C++,右半窗格選擇「編譯器」 (3) 「編譯器」輸入 C:\Dev-cpp\bin\gcc.exe 「參數 」設 -o "%Dir%%Name%.exe" "%File%" 「編譯後執行」設 cmd /c "%Dir%%Name%.exe" &pause 下面再勾選 編譯前儲存所有檔案、擷取程式輸出結果。 「編譯器」那裡,若已安裝了 MinGW,建議不要再設 Dev-cpp 裡之 gcc 版本差太多,一個是 3.4.2,一個是 4.5.2 路徑設 C:\MinGW32\bin\gcc.exe 若 MinGW 已有註冊環境變數的話,可直接輸入 gcc.exe 即可, 用不到 Dev-cpp 的話,也可把它移除。 若是慣用 C++ 寫的話,該設的是 g++.exe,非 gcc.exe。 好了之後每次用 PSPad 寫好碼,直接輸入 Ctrl+F9, 編譯器給的所有錯誤與警告訊息,會出現在下面之 Log 視窗, 若無誤時將會執行所生成之檔案。 這方法有缺點,一次只能編譯生成一個檔案出來,下面再說一點點 batch。 伍、 完全不使用 IDE, 只想看 source code 產生之結果 通常我收到「一陀檔案」,說他的程式沒錯,第一個動作是先看執行結果時, 我並不會直接開任何 IDE 出來,這樣要把所有檔案都拉到 IDE 裡面去, 我用的是 batch 方式產生。 在桌面上建立一個 Toilet.bat,內容如下 @echo off setlocal enabledelayedexpansion SET "instr="c:\Dev-Cpp\bin\gcc.exe" -o "%~dp1dev_c_multi.exe"" FOR %%I IN (%*) DO ( SET instr=!instr! "%%~I" ) SET instr=!instr! -O2 !instr! "%~dp1dev_c_multi.exe" endlocal echo. &pause 上面的 "c:\Dev-Cpp\bin\gcc.exe" 這一樣可以改, 我預設輸出檔名是 dev_c_multi.exe,使用方式不用在命令提示字元底下一一輸入, 而且 直接把 "所有" 用到的 .c .h 全都拖到 Toilet 裡面去。 就像是要刪除檔案,把檔案拖到資源回收桶裡面一樣, 只是這次是把所有檔案拖到廁所(Toilet.bat)裡面去。 編譯失敗會顯示錯誤訊息,編譯成功時,會在檔案的地方產生出 dev_c_multi.exe, 並會執行它。 visual c++ 我也寫了一份, @echo off call "%VS100COMNTOOLS%vsvars32.bat" %~d1 cd %~d1 cd "%~dp1" setlocal enabledelayedexpansion SET "instr=CL.exe /Fe"%~dp1v10_noOpt.exe" " FOR %%I IN (%*) DO ( CL.exe /Fo"%%~dpnI.obj" %%I SET instr=!instr! "%%~dpnI.obj" ) !instr! endlocal echo. &echo compile finish, execute now... pause & cls "%~dp1v10_noOpt.exe" del "%~dp1*.obj" pause 上述以 visual c++ 2010 為例,要換成是 2008 的話改 "%VS90COMNTOOLS%vsvars32.bat" ,預設檔名為 vc10_noOpt.exe。 使用方式一樣是拖進來即可。 上面這些用 batch 完成,是「無腦」方式, compile 過程中勢必會有些警告出來, 但若單純在寫 console 程式,應還算勘用。 陸、 PSPad 多檔編譯 新增 PSPad 專用之 batch file 基於 第肆點 所產生之缺點,加上第五點,其實我們已可在 PSPad 下連結起所有相關之 .h / .c / .cpp,這裡再新增一個 DevC.bat, 內容如下 @echo off SET "MyPath=%~dpf1" SET "MyPath="%MyPath%\*.h" "%MyPath%\*.c" /b" SET "Output="%~dpf1Main.exe"" SET /P UserInput=Input the execute filename(Default:%Output%): IF NOT "%UserInput%"=="" SET "Output="%~dpf1%UserInput%.exe"" SET "Instr=C:\Dev-Cpp\bin\gcc.exe -o %Output% " SETLOCAL EnableDelayedExpansion FOR /F "tokens=* delims=" %%A in ('dir !MyPath! /b') DO ( :: echo %%A SET Instr=!Instr! "%~dpf1%%A" ) %Instr% ENDLOCAL echo. &echo compile finished, it will execute now.. pause & cls %Output% pause 完成之後,存在 C:\ 底下,絕對路徑為 C:\DevC.bat 與上述一樣,若有安裝 MinGW ,建議Instr=C:\Dev-Cpp\bin\gcc.exe 改為 Instr=C:\MinGW32\bin\gcc.exe ,C++ 的話除了將 gcc 改 g++ 外 "%MyPath%\*.c" 改成 "%MyPath%\*.cpp"。 PSPad 下之設定 在 PSPad 那裡之設定如下所述 (1) 點擊 「設定」、「語法高亮設定」 (2) 點擊 「C/C++」、「編譯器」 (3) 「編譯器」設 「C:\DevC.bat」 「參數 」設 「"%Dir%"」, 其他清空,而 Log 之 CheckBox 只勾 「編譯前儲存檔案」, 其它的「擷取程式的輸出結果」、「隱藏輸出視窗」千千萬萬不要勾。 實際上這改善方案仍有限,它是指定當下 Active File 之路徑, 去找該資料夾底下之所有 .c/.cpp 與 .h,同時把它們全都抓進來編譯, 意思是如果找到該資料夾底下,檔案內容有兩個 main ,那就失敗了。 其實最好之方式,應是去分析該 PSPad 之 project file - .ppr, 但問題已愈來愈複雜,此處僅以概述,不再深入進去。 實際操作流程 實際上,在 PSPad 裡按下 Ctrl+F9 時,程式會提示,請輸入一輸出檔名, 這裡預設是 (資料夾路徑\Main.exe),如果直接按 Enter 的話,就以預設輸出; 如果輸入 a 的話,輸出會放在 (資料夾路徑\a.exe),自動加上 .exe, 若不想每次自己手動輸入,想直接生成的話,在上面之 DevC.bat 裡面, SET /P UserInput=Input the execute filename(Default:%Output%): IF NOT "%UserInput%"=="" SET "Output="%~dpf1%UserInput%.exe"" 這兩行直接刪除它。完成之後,若順利 compile 出執行檔,程式也會自動執行。 柒、 其他未盡與注意事項 本文其實有點用硬爆法把要的結果爆出來, (好的方法其實不想再花時間去橋), 過程中用到不算淺的 batch command,若要再自己做客制化之環境,有幾個建議 可再供參考 1. 弄熟 make.exe / cmake.exe / nmake.exe(for vs) 2. 弄熟 batch command 3. 弄熟 gcc.exe / g++.exe / CL.exe 4. 弄熟 pspad/ultraedit 之環境變數 用 UltraEdit , PSPad , Notepad++ 這類型軟體當輔助 IDE,只能開發一些簡單之 程式,若程式本身架構複雜,並不適合用這類型小軟體協助,缺點為在 linker , compiler 那裡浪費不少不必要時間,且其並無 IDE 開發環境下之 debugger 來得簡便。 若認為此文敘述有所不妥,或敘述上有所誤失、觀念不正確, 或有其他建議者,請不吝指出、補充、指教,小弟當感激不盡。 -- YouLoveMe() ? LetItBe() : LetMeFree(); -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 180.177.78.41
diabloevagto:不推別人以為我看不懂! 09/20 19:02
diabloevagto:notepad++也很棒喔! 09/20 19:07
diabloevagto:推薦 程式設計師的自我修養:連結、載入、程式庫 09/20 19:10
notepad++ 我還沒摸過,寫得不錯之編輯軟體應都有支援這部份, 純粹只因摸過 UltraEdit / PSPad, 兩者相較下我選用 PSPad (免費)
ariesd:推MinGW+Vim,不推Dev-C++。 09/20 20:07
tropical72:謝謝推書。另本文其實是想讓 Dev-C++ 使用者跳出來, 09/20 20:22
tropical72:故才以 Dev-C++ 為例,了解流程後其實也不再限於 IDE.. 09/20 20:23
weiyucsie:有種編譯和組譯搞錯的感覺XD 09/20 21:54
weiyucsie:(跑去翻wikipedia :p) 09/20 22:00
compiler , assembler , 這個真的是我弄反了,已更正,謝謝指出。 :)
lsc36:推推 第二頁有個地方打成TMD-gcc了XD 09/20 22:04
james732:我以為TMD-gcc是故意的耶?XD 09/20 22:18
我也以為那是 TMD-gcc,查證後是 TDM-gcc,感謝 lsc36 指正。
firejox:我傾向用geany做小型IDEXDD 09/20 22:35
firejox:geany 裝好後在設完環境變數後就可以使用了XDD 09/20 22:36
firejox:像linker這種事就交給makefile(逃~~ 09/20 22:41
tropical72:geany 是 linux 底下的? linker 用 make 無庸致疑, 只 09/20 22:42
tropical72:是現在我大多還是搞 batch, 是該找時間補 makefile. 09/20 22:42
firejox:geany 也有windows的呀(雖然某些顯示有點怪怪的) 09/20 22:43
Bencrie:不用 IDE 話有 Makefile 就夠了,不然就 cmake 09/20 22:45
firejox:在windows下 還是先把路徑設一設比較方便... 09/20 22:52
tropical72:不用IDE的話,一般還是會希望有high light 之軟體吧.. 09/20 23:08
firejox:恩恩 highlight 是editor裡最偉大的發明(對programer而言) 09/20 23:26
llewxam:有種tex進化到pdflatex的味道XD 09/20 23:36
stonehomelaa:vim + gcc!! 09/21 00:19
kasase:gvim搞定一切,讚 09/21 00:38
VictorTom:推:) 09/21 01:35
xatier:好文給個推! 09/21 07:09
uranusjr:從 IDE 直接衝 CMake 也太硬了吧XD 09/21 08:38
littleshan:拜託別再用 makefile 了 09/21 12:23
shadow0326:為什麼不能用makefile QQ 09/21 14:10
lmr3796:makefile有什麼不好嗎QQ 09/21 14:20
littleshan:1. makefile內部寫死compile指令,換compiler很麻煩 09/21 14:45
littleshan:2.難以處理不同的build如debug/release/shared/static 09/21 14:45
littleshan:3. 隱藏的dependency很麻煩,makedepend只能處理.h 09/21 14:47
littleshan:去看一下cmake/bjam/scons這些都是很棒的替代方案 09/21 14:49
Bencrie:$(CC) $(CXX) 可以換吧 orz 09/21 15:03
littleshan:參數不一樣啊... 09/21 15:07
Bencrie:那 ... 全部用變數取代掉好了 XDD 09/21 15:07
shadow0326:目前我的Makefile還真的是全用變數 @_@" 09/21 15:13
shadow0326:而且分開make debug和make release @_@" 09/21 15:14
Bencrie:不過這樣 Makefile 應該會很難讀喔 XD 09/21 15:17
kingweirong:好文推~ 09/22 11:44
bill42362:請問一下 CMake 能夠使用多 compiler 嗎? 09/22 19:11
bill42362:比方說小弟的專案 .cu 需要 nvcc 而 .c 則要 gcc 這樣@@ 09/22 19:12
Bencrie:可能要靠 custom command 把 .cu 指給 nvcc 09/23 12:52
※ 編輯: tropical72 來自: 180.177.78.41 (09/27 00:29)