2019年12月3日火曜日

コマンドラインからVisual Studioの仕組みを学ぶ2

前回はこちら
コマンドラインからVisual Studioの仕組みを学ぶ

マクロによるDebug版とRelease版の切り替え


さて,次のように_DEBUGの有無でデバッグ時とそれ以外で処理を変える,といったコードを書いたことはあるでしょうか?

#include <iostream>
using namespace std;

int main()
{
#if defined(_DEBUG)
    cout << "Debug" << endl;
#else
    cout << "Release" << endl;
#endif
}

この例だとあまり意味はないですが,例えば開発中のみデバッグ機能を有効にしたり,特別にログを出力するようにするなど,こういった書き方をすることは良くあります.

ところで,この _DEBUG というマクロはどこで定義されているのでしょうか? また,定義されていたとすると,デバッグ機能を無効にしたい場合は,わざわざ消さないといけないのでしょうか?

そんな面倒なことはしません.コマンドラインのオプションでマクロを定義することができます.これにより,コンパイル時にデバッグ有り版とデバッグ無し版を切り替えることができます.

マクロの定義には "/D マクロ" という書き方をします.

次のコマンドでは,_DEBUGが定義された状態でコンパイルします.
cl /EHsc /D _DEBUG main.cpp

一方,次のコマンドでは,_DEBUGが定義されていない状態でコンパイルします.
cl /EHsc main.cpp

ソースコードを読んでいて,どこにも定義されていないマクロに遭遇したことがあるかもしれません.そういったマクロは,このようにコンパイル時に定義されているのです.

Visual Studioのプロパティとしては,C/C++のプリプロセッサのプリプロセッサの定義になります.このプロパティは ; 区切りでマクロが定義されていて,コンパイル時にはそれを分解して,それぞれを /D と一緒にコンパイラに渡しているわけです.

プロパティの左上にある構成をDebugやReleaseで切り替えると,このプリプロセッサの定義,が変わることが分かります.

Visual Studioでは,DebugやReleaseといった目的やx64などのプラットフォームの組み合わせ毎に,こういった定義を設定することができて,その設定に合わせてコンパイラにマクロを渡してくれているわけです.

clangの場合,-D でマクロが定義できます.似ていますね.そして,clangを使っているXcodeでも,同じようにマクロを定義する項目があります.

まとめ

/D マクロ,でコンパイル時にマクロを定義した状態でコンパイルすることができます.
DebugやReleaseといった構成やx64などのプラットフォームを切り替えると,プロパティのプリプロセッサの定義が切り替わり,/D の形にしてコンパイラに渡してくれます.

おまけ

Windows.hを開いてみると,色々とコードを変更するためのマクロが書いています.特に,NOMINMAXは,次のようなコードがちゃんとコンパイルできるようにするために必要です.

#include <iostream>
#include <cmath>

int main()
{
 std::cout << std::min(1, 2) << endl;
}

どうしてNOMINMAXが必要なのか,実際に確かめてみると理解が深まるかもしれません.

ついでに,_USE_MATH_DEFINESについても調べておくと,役立つときがあるかもしれません.

0 件のコメント:

コメントを投稿