#navi_header|C言語系| "Hello, World!"レベルの単純なプログラムを題材に、基本的なコンパイルオプションのまとめ。 対象:Visual C++ 2008 Express Edition > cl Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. > link Microsoft (R) Incremental Linker Version 9.00.30729.01 Copyright (C) Microsoft Corporation. All rights reserved. ここではコンソール/GUI/DLLに関わらず共通して使われそうなオプションをまとめてみた。 #more|| #outline|| ---- * コマンドラインでコンパイルする基本(clコマンド) シンプルな基本: HelloWorld.c: #code|c|> #include int main() { printf("Hello, World!\n"); return 0; } ||< コンパイル: #pre||> > cl HelloWorld.c Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. HelloWorld.c Microsoft (R) Incremental Linker Version 9.00.30729.01 Copyright (C) Microsoft Corporation. All rights reserved. /out:HelloWorld.exe HelloWorld.obj ||< 実行: > HelloWorld.exe Hello, World! * 最適化無し(/Od), 著作権情報表示無し(/nolog), 全警告表示(/Wall, /Wn) : /Od : 最適化無し : /nolog : 著作権情報表示無し : /Wall, /Wn(nは数字) : "/Wall"で全警告を表示。あるいは"/W1" - "/W4"。IDEでWin32コンソールアプリのプロジェクトを作成すると、デフォルトは"/W3"になっている。 HelloWorld.c: #code|c|> #include int main(int argc, char *argv[]) { printf("Hello, World!\n"); return 0; } ||< コンパイル:"/Wall" #pre||> > cl /Od /nologo /Wall HelloWorld.c HelloWorld.c C:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE\stdio.h(381) : \ warning C4255: '_get_printf_count_output' : 関数プロトタイプがありません \ : '()' を '(void)' に変換します。 HelloWorld.c(3) : warning C4100: 'argv' : 引数は関数の本体部で 1 度も参照されません。 HelloWorld.c(3) : warning C4100: 'argc' : 引数は関数の本体部で 1 度も参照されません。 ||< コンパイル:"/W3" #pre||> > cl /Od /nologo /W3 HelloWorld.c HelloWorld.c ||< * 複数モジュールの分割コンパイル(/c, LINKコマンド) : /c : ".obj"ファイルの作成までで、リンクは行わない main.c: #pre||> #include extern int foo(int a, int b, int c, int d); extern int bar(int a, int b, int c, int d); int main(int argc, char *argv[]) { int r; r = foo(4, 3, 2, 1); printf("foo() = %d\n", r); r = bar(4, 3, 2, 1); printf("bar() = %d\n", r); return 0; } ||< foo.c: #pre||> int foo(int a, int b, int c, int d) { int r; r = a + b + c + d; return r; } ||< bar.c: #pre||> int bar(int a, int b, int c, int d) { int r; r = a - b - c - d; return r; } ||< 分割コンパイル: #pre||> > cl /c foo.c Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. foo.c > cl /c bar.c Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. bar.c > cl /c main.c Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. main.c ||< 手動でリンク:先頭に指定した".obj"ファイル名で".exe"が生成される。 #pre||> > link main.obj foo.obj bar.obj Microsoft (R) Incremental Linker Version 9.00.30729.01 Copyright (C) Microsoft Corporation. All rights reserved. > main.exe foo() = 10 bar() = -2 ||< foo.objを先頭に指定すると、"foo.exe"が生成される。 #pre||> > link foo.obj main.obj bar.obj Microsoft (R) Incremental Linker Version 9.00.30729.01 Copyright (C) Microsoft Corporation. All rights reserved. > foo.exe foo() = 10 bar() = -2 ||< "/OUT:filename"でファイル名を指定出来る。 #pre||> > link /OUT:foobarmain.exe main.obj foo.obj bar.obj Microsoft (R) Incremental Linker Version 9.00.30729.01 Copyright (C) Microsoft Corporation. All rights reserved. > foobarmain.exe foo() = 10 bar() = -2 ||< * "C" or "C++"の指定(/TC, /TP) デフォルトでは拡張子から自動判別する。次のオプションを指定することで、明示的に入力ソースファイルの言語が"C"か"C++"かを指定出来る。 : /TC : コマンドラインで指定されたコンパイル対象のソースファイルを全てC言語として扱う : /TP : コマンドラインで指定されたコンパイル対象のソースファイルを全てC++言語dとして扱う "/TC"のテスト版:HelloWorld_TCtest.foo: #pre||> #include /* C style multi line comment */ // C++ style single line comment int main(int argc, char *argv[]) { printf("Hello, World!\n"); return 0; } ||< コンパイル&実行: #pre||> > cl /TC HelloWorld_TCtest.foo Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. HelloWorld_TCtest.foo Microsoft (R) Incremental Linker Version 9.00.30729.01 Copyright (C) Microsoft Corporation. All rights reserved. /out:HelloWorld_TCtest.exe HelloWorld_TCtest.obj > HelloWorld_TCtest.exe Hello, World! ||< "/TP"のテスト版:HelloWorld_TPtest.foo: #pre||> #include using namespace std; int main() { cout << "Hello, World!" << endl; return 0; } ||< コンパイル&実行: #pre||> > cl /TP HelloWorld_TPtest.foo Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. HelloWorld_TPtest.foo C:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE\xlocale(342) : warning C4530: \ C++ 例外処理を使っていますが、アンワインド セマンティクスは有効にはなりません。\ /EHsc を指定してください。 Microsoft (R) Incremental Linker Version 9.00.30729.01 Copyright (C) Microsoft Corporation. All rights reserved. /out:HelloWorld_TPtest.exe HelloWorld_TPtest.obj > HelloWorld_TPtest.exe Hello, World! ||< "/EHsc"指定を行うと上記警告は消える: #pre||> > cl /TP /EHsc HelloWorld_TPtest.foo Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. HelloWorld_TPtest.foo Microsoft (R) Incremental Linker Version 9.00.30729.01 Copyright (C) Microsoft Corporation. All rights reserved. /out:HelloWorld_TPtest.exe HelloWorld_TPtest.obj ||< * コメント形式とMicrosoftのC/C++言語拡張機能の有効・無効切り替え(/Za, /Ze) VC++2008のC/C++コンパイラでは、デフォルトではMicrosoftによるC/C++言語拡張機能が有効化されている。 これにより、C言語としてコンパイルする場合でもC++形式の一行コメント、"//"が使えるようになっている。 : /Za : MicrosoftによるC/C++言語拡張機能を無効にする。Cソースの場合、"//"は警告になる。 : /Ze : MicrosoftによるC/C++言語拡張機能を有効にする。(デフォルト) 一行コメントの場合、エスケープシーケンスが行末にあると次の行もコメントとして認識するようになっている。ただし、実際に使ってみると、以下の警告が表示される。 warning C4010: 単一行コメント (//) に、行連結文字があります。 また、"/Ze"の明示的な指定は現在推奨されていないらしい。下記に示すように今後のバージョンからは削除される旨の警告が表示される。 コメントスタイル検証用:HelloWorld_TCtest.foo: #pre||> #include /* C style multi line comment */ // C++ style single line comment int main(int argc, char *argv[]) { printf("Hello, World!\n"); return 0; } ||< "/Ze"でコンパイル: #pre||> > cl /Ze /TC HelloWorld_TCtest.foo Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. cl : コマンド ライン warning D9035 : オプション 'Ze' の使用は現在推奨されていません。\ 今後のバージョンからは削除されます。 HelloWorld_TCtest.foo Microsoft (R) Incremental Linker Version 9.00.30729.01 Copyright (C) Microsoft Corporation. All rights reserved. /out:HelloWorld_TCtest.exe HelloWorld_TCtest.obj ||< "/Za"でコンパイル: #pre||> > cl /Za /TC /W3 HelloWorld_TCtest.foo Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. HelloWorld_TCtest.foo Microsoft (R) Incremental Linker Version 9.00.30729.01 Copyright (C) Microsoft Corporation. All rights reserved. /out:HelloWorld_TCtest.exe HelloWorld_TCtest.obj ||< "/Za"でも、"/W3"までの警告指定では単一行コメントについては警告もエラーも表示されなかった。 "/W4"まで警告レベルを上げることで、警告が表示されるようになる。 #pre||> > cl /Za /TC /W4 HelloWorld_TCtest.foo Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. HelloWorld_TCtest.foo C:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE\sal.h(108) : \ warning C4001: 標準外の言語拡張 (単一行コメント) が行われています。 HelloWorld_TCtest.foo(6) : warning C4100: 'argv' : 引数は関数の本体部で 1 度も参照されません。 HelloWorld_TCtest.foo(6) : warning C4100: 'argc' : 引数は関数の本体部で 1 度も参照されません。 Microsoft (R) Incremental Linker Version 9.00.30729.01 Copyright (C) Microsoft Corporation. All rights reserved. /out:HelloWorld_TCtest.exe HelloWorld_TCtest.obj ||< * インクルードパスの調整(/I, /X) : /I : インクルードディレクトリを追加する。複数指定したい場合は、ディレクトリの分だけ "/I ディレクトリ名"を指定する。 : /X : 標準のインクルードディレクトリを無視する。 実験用のファイル構成: pptest.c inc/ pptest.h pptest.c: #pre||> #include "pptest.h" /** * comment1 */ int foo(int a, int b) { return a + b; } /** * comment2 */ int bar(int a, int b) { return a * b; } ||< pptest.h: #pre||> #ifdef _DEBUG char message[] = "Debug Message"; #else char message[] = "Release Message"; #endif /* _DEBUG */ ||< 実験1:"/I"を指定しない→コンパイルエラー(fatal error C1083) #pre||> > cl /c pptest.c Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. pptest.c pptest.c(1) : fatal error C1083: include ファイルを開けません。'pptest.h': No such file or directory ||< 実験2:"/I"を指定→コンパイル成功 #pre||> > cl /c /I .\inc pptest.c Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. pptest.c > dir pptest.obj (...) 2010/02/11 11:46 625 pptest.obj 1 個のファイル 625 バイト (...) ||< 実験3:pptest.cでstdio.hをインクルードさせた上で、"/X"で標準インクルードディレクトリを無視させる→コンパイルエラー(fatal error C1083) #pre||> > cl /c /X /I .\inc pptest.c Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. pptest.c pptest.c(1) : fatal error C1083: include ファイルを開けません。'stdio.h': No such file or directory ||< * プリプロセス結果を取得(コンパイルは行わない)(/P, /E, /EP, /C) : /P : "#line"付でプリプロセス出力がファイルに保存される。ファイル名はソースファイル名のbasename + ".i"。 : /E : "#line"付でプリプロセス出力が標準出力に出力される。 : /EP : "#line"無しでプリプロセス出力を標準出力に出力、あるいは"/P"との組み合わせでファイルに保存する。 : /C : プリプロセス時にコメントを保持する。 「インクルードパスの調整」で使ったpptest.c, pptest.hを使って実験してみる。 ※見やすくする為、プリプロセス結果中の連続する空行は一行に縮めています。 ** "/E"で標準出力へ #pre||> > cl /E /I .\inc pptest.c Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. pptest.c #line 1 "pptest.c" #line 1 ".\\inc\\pptest.h" char message[] = "Release Message"; #line 6 ".\\inc\\pptest.h" #line 2 "pptest.c" int foo(int a, int b) { return a + b; } int bar(int a, int b) { return a * b; } ||< ** "/EP"で"#line"無しで標準出力へ+コメント保持 #pre||> > cl /EP /C /I .\inc pptest.c Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. pptest.c char message[] = "Release Message"; /** * comment1 */ int foo(int a, int b) { return a + b; } /** * comment2 */ int bar(int a, int b) { return a * b; } ||< ** "/P"で"#line"付きでファイルへ保存 #pre||> > cl /D _DEBUG /P /C /I .\inc pptest.c Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. pptest.c ||< 保存されたファイル内容:pptest.i: #pre||> #line 1 "pptest.c" #line 1 ".\\inc\\pptest.h" char message[] = "Debug Message"; #line 6 ".\\inc\\pptest.h" #line 2 "pptest.c" /** * comment1 */ int foo(int a, int b) { return a + b; } /** * comment2 */ int bar(int a, int b) { return a * b; } ||< ** "/P" + "/EP"で"#line"無しでファイル保存 #pre||> > cl /D _DEBUG /P /EP /C /I .\inc pptest.c Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. pptest.c ||< 保存されたファイル内容:pptest.i: #pre||> char message[] = "Debug Message"; /** * comment1 */ int foo(int a, int b) { return a + b; } /** * comment2 */ int bar(int a, int b) { return a * b; } ||< * アセンブラコードを出力(/FA) ※いずれのオプションでもコンパイル以降の処理も続行される。 : /FA : アセンブラコードのみの".asm"ファイルを生成 : /FAc : 対応するマシン語が埋め込まれたアセンブラコードを生成(拡張子:".cod") : /FAs : 対応するソースコードが埋め込まれたアセンブラコードを生成(拡張子:".asm") : /FAcs or /FAsc : 対応するマシン語+対応するソースコードが埋め込まれたアセンブラコードを生成(拡張子:".cod") 実験ファイル:fatest.c: #pre||> int foo(int a, int b, int c) { int r; r = a + b + c; r *= 3; return r; } ||< ** /FA : シンプルな ".asm" #pre||> > cl /c /Od /FA fatest.c Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. fatest.c ||< fatest.asm: #pre||> ; Listing generated by Microsoft (R) Optimizing Compiler Version 15.00.30729.01 TITLE C:\in_vitro\c\cltest02\fatest.c .686P .XMM include listing.inc .model flat INCLUDELIB LIBCMT INCLUDELIB OLDNAMES PUBLIC _foo ; Function compile flags: /Odtp _TEXT SEGMENT _r$ = -4 ; size = 4 _a$ = 8 ; size = 4 _b$ = 12 ; size = 4 _c$ = 16 ; size = 4 _foo PROC ; File c:\in_vitro\c\cltest02\fatest.c ; Line 2 push ebp mov ebp, esp push ecx ; Line 4 mov eax, DWORD PTR _a$[ebp] add eax, DWORD PTR _b$[ebp] add eax, DWORD PTR _c$[ebp] mov DWORD PTR _r$[ebp], eax ; Line 5 mov ecx, DWORD PTR _r$[ebp] imul ecx, 3 mov DWORD PTR _r$[ebp], ecx ; Line 6 mov eax, DWORD PTR _r$[ebp] ; Line 7 mov esp, ebp pop ebp ret 0 _foo ENDP _TEXT ENDS END ||< ** /FAc : マシン語付 ".cod" #pre||> > cl /c /Od /FAc fatest.c Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. fatest.c ||< fatest.cod: #pre||> ; Listing generated by Microsoft (R) Optimizing Compiler Version 15.00.30729.01 TITLE C:\in_vitro\c\cltest02\fatest.c .686P .XMM include listing.inc .model flat INCLUDELIB LIBCMT INCLUDELIB OLDNAMES PUBLIC _foo ; Function compile flags: /Odtp _TEXT SEGMENT _r$ = -4 ; size = 4 _a$ = 8 ; size = 4 _b$ = 12 ; size = 4 _c$ = 16 ; size = 4 _foo PROC ; File c:\in_vitro\c\cltest02\fatest.c ; Line 2 00000 55 push ebp 00001 8b ec mov ebp, esp 00003 51 push ecx ; Line 4 00004 8b 45 08 mov eax, DWORD PTR _a$[ebp] 00007 03 45 0c add eax, DWORD PTR _b$[ebp] 0000a 03 45 10 add eax, DWORD PTR _c$[ebp] 0000d 89 45 fc mov DWORD PTR _r$[ebp], eax ; Line 5 00010 8b 4d fc mov ecx, DWORD PTR _r$[ebp] 00013 6b c9 03 imul ecx, 3 00016 89 4d fc mov DWORD PTR _r$[ebp], ecx ; Line 6 00019 8b 45 fc mov eax, DWORD PTR _r$[ebp] ; Line 7 0001c 8b e5 mov esp, ebp 0001e 5d pop ebp 0001f c3 ret 0 _foo ENDP _TEXT ENDS END ||< ** /FAs : 元のソースコード付 ".asm" #pre||> > cl /c /Od /FAs fatest.c Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. fatest.c ||< fatest.asm: #pre||> ; Listing generated by Microsoft (R) Optimizing Compiler Version 15.00.30729.01 TITLE C:\in_vitro\c\cltest02\fatest.c .686P .XMM include listing.inc .model flat INCLUDELIB LIBCMT INCLUDELIB OLDNAMES PUBLIC _foo ; Function compile flags: /Odtp ; File c:\in_vitro\c\cltest02\fatest.c _TEXT SEGMENT _r$ = -4 ; size = 4 _a$ = 8 ; size = 4 _b$ = 12 ; size = 4 _c$ = 16 ; size = 4 _foo PROC ; 2 : { push ebp mov ebp, esp push ecx ; 3 : int r; ; 4 : r = a + b + c; mov eax, DWORD PTR _a$[ebp] add eax, DWORD PTR _b$[ebp] add eax, DWORD PTR _c$[ebp] mov DWORD PTR _r$[ebp], eax ; 5 : r *= 3; mov ecx, DWORD PTR _r$[ebp] imul ecx, 3 mov DWORD PTR _r$[ebp], ecx ; 6 : return r; mov eax, DWORD PTR _r$[ebp] ; 7 : } mov esp, ebp pop ebp ret 0 _foo ENDP _TEXT ENDS END ||< ** /FAcs or /FAsc : マシン語+元のソース付 ".cod" #pre||> > cl /c /Od /FAsc fatest.c Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. fatest.c ||< fatest.cod: #pre||> ; Listing generated by Microsoft (R) Optimizing Compiler Version 15.00.30729.01 TITLE C:\in_vitro\c\cltest02\fatest.c .686P .XMM include listing.inc .model flat INCLUDELIB LIBCMT INCLUDELIB OLDNAMES PUBLIC _foo ; Function compile flags: /Odtp ; File c:\in_vitro\c\cltest02\fatest.c _TEXT SEGMENT _r$ = -4 ; size = 4 _a$ = 8 ; size = 4 _b$ = 12 ; size = 4 _c$ = 16 ; size = 4 _foo PROC ; 2 : { 00000 55 push ebp 00001 8b ec mov ebp, esp 00003 51 push ecx ; 3 : int r; ; 4 : r = a + b + c; 00004 8b 45 08 mov eax, DWORD PTR _a$[ebp] 00007 03 45 0c add eax, DWORD PTR _b$[ebp] 0000a 03 45 10 add eax, DWORD PTR _c$[ebp] 0000d 89 45 fc mov DWORD PTR _r$[ebp], eax ; 5 : r *= 3; 00010 8b 4d fc mov ecx, DWORD PTR _r$[ebp] 00013 6b c9 03 imul ecx, 3 00016 89 4d fc mov DWORD PTR _r$[ebp], ecx ; 6 : return r; 00019 8b 45 fc mov eax, DWORD PTR _r$[ebp] ; 7 : } 0001c 8b e5 mov esp, ebp 0001e 5d pop ebp 0001f c3 ret 0 _foo ENDP _TEXT ENDS END ||< * その他使うかも知れないオプション : /Fd : "/ZI"などデバッグ情報オプション指定時に生成されるプログラムデータベース(PDB)ファイル名を "/Fdpathname" で指定する。 : /Fe : "/Fepathname"でコンパイラにより生成されるexe/dllのファイル名とディレクトリを指定する。"/c"オプション付きの場合は無効になる。 : /Fd : "/Fdpathname"で".obj"ファイル名を指定する。 : /Oy : フレームポインタの省略(x86専用) : /Z7, /Zi, /ZI : デバッグ情報の形式を指定する。 : /Zp : 構造体メンバの配置、パッキング(/Zp{1|2|4|8|16}) : /Zs : 構文をチェックするだけ。 #navi_footer|C言語系|