ラベル Visual Studio の投稿を表示しています。 すべての投稿を表示
ラベル Visual Studio の投稿を表示しています。 すべての投稿を表示

2021年12月16日木曜日

Visual Studio でライブラリなど外部コードの警告を出さないようにする方法

これは「C++のカレンダー | Advent Calendar 2021 - Qiita」の16日目の記事です。

はじめに

警告はときにプログラムの問題を教えてくれます。
警告は基本的にないのが望ましいです。なぜなら、野原から四葉のクローバーを探し出すのは大変だからです。(見つけた四葉は幸運をもたらすか、不幸をもたらすか。。見つけるなら早いほうがいいですよ)

CI/CD 担当をやっていると警告を直してもらうための対応とかしたりします。
警告出てたらステータスを変えて通知とか、ちょっとずつ警告をエラーにしていくとか。
ここで問題になるのは、自分たちが改変することができない SDK やライブラリの警告です。
通知で頑張ってる場合はフィルターでなんとかなるかもしれません。
as Error にしている場合は困ります。

そんな場合は自分たちのコード以外をシステムインクルード(#include <...>)し別途警告レベルを制御することで解決できます。

Visual Studio で外部コードの警告を制御する

Visual Studio では 2017 (15.6) からシステムインクルードの警告レベルを別途設定できるようになりました。「/external (外部ヘッダー診断) | Microsoft Docs」こちらの公式ドキュメントにもありますが 2017 では試験機能となっています。/external オプションに加えて /experimental:external オプションも必要になるので注意してください。2019 からは正式機能となっており、設定も専用のページができました。

さて、これを利用すれば外部コードはシステムインクルードとすることで警告がでないようにできます。試しに以下のコードで試してみました。


/external の設定

プロジェクトプロパティの「C/C++」→「外部インクルード」を開き、 /external:W0 を設定します。コード分析も外部インクルードに対して別途制御可能なので、有効にしている場合は設定しましょう。

外部インクルードディレクトリにパスを追加している場合は、システムインクルードすれば外部インクルードとして認識されます。もしただのインクルードディレクトリにパスを追加している場合は、/external:anglebracket オプションを有効にすることで外部インクルードとみなされます。(システムインクルードすれば警告でなくなると逃げ口として意図しない対応をされる可能性があるので、インクルードディレクトリの設定を変更するのをオススメします)

システムインクルードではない場合

C4390 と C4456 が出ます。

システムインクルードの場合

システムインクルードにすると警告が消えました!

消えない警告もある?

たまたま見つけたのですが、システムインクルードしたファイルの警告でも /external:W0 が効かずに警告されるケースがありました。(こういう書き方をすることはない気もしますが)
コードはこちらです。gcc/clang では警告されませんでした。(https://wandbox.org/permlink/kPn2z1MLCAvbOBny)

↑は C4390/C4702 の2つ。↓は C4390 は消えるが、C4702 は消えない。

Visual Studio でシステムインクルードヘッダーの警告を厳しくする

逆にシステムインクルードの警告レベルを上げるとどうなるのでしょうか?
標準ライブラリはシステムインクルードしていると思いますが、それらのコードに警告はあるのか・・? /external:W4 にして試してみました。


結果としては警告は出ない、が警告があるのかないのかはわからない。でした。
というのも VS2017 より前から標準ライブラリの警告って見た記憶がないため(たぶん)、別途制御されているのでは?と思ったからです。
ちなみに後述してますが gcc/clang では(とあるコンパイルオプションをつけると)標準ライブラリからも警告が出ていたこともあります。
MSVC の STL は公開されているので、暇なときにビルドしてみて確認してみようかと思います。
https://github.com/microsoft/STL

gcc/clang の場合

gcc/clang の場合は古くからシステムインクルードの警告は除外されていました。
(Visual Studio が今までできてなくて 2017 でようやくという感じでした)
Wandbox で試してみたのでリンクを貼っておきます。
コードは Gist にも置いてあります。

システムインクルードではない場合

警告でます。
gcc: https://wandbox.org/permlink/MLrLASaM5o5A3UWm
clang: https://wandbox.org/permlink/x6TT2NFROSmyLhV4


システムインクルードの場合

警告でません。
gcc: https://wandbox.org/permlink/XVHXnWIMyOfDMjl3
clang: https://wandbox.org/permlink/strTYwduT4ZLH5NK

gcc/clang でシステムインクルードヘッダーの警告を有効にする

gcc/clang でもシステムインクルードの警告を有効にできます。-Wsystem-headers オプションを使います。
試しにしてみると・・

新しいコンパイラーと標準ライブラリの組み合わせだと警告でませんでした。
古いとそこそこ出ます。

gcc 9.1.0: https://wandbox.org/permlink/lhXWuNvWEJdKwJNh
gcc 8.3.0: https://wandbox.org/permlink/4dHKZKtdqmDGmXNU 
clang 6.0.0: https://wandbox.org/permlink/MaVYzrGDeT79eMZa
clang 5.0.0: https://wandbox.org/permlink/qjbmV9U2c8MxHe6A

まとめ

システムインクルードを使って外部コードの警告を除外、自身のコードの警告を取り除く/取り除いてもらうように自動化/自働化しましょう。

2020年10月26日月曜日

[C++][IWYU] Include What You Use CL を VS2019 対応しました

include-what-you-use-cl を VS2017/VS2019 に対応しました。
include-what-you-use-ci (以下 IWYU-CL) は include-what-you-use (以下 IWYU) を Visual Studio のプラットフォームツールセットとして選択できるようにするツールです。
プラットフォームツールセットとすることでプロジェクトの設定(インクルードパスなど)をそのまま利用して IWYU をかけることを目的に作りました。
VS2017 から VS{version}COMNTOOLS 環境変数がなくなったりと、インクルード関連の構成が一新されてから更新が滞ってましたが、最近 vswhere の存在を知り更新することにしました。

あと同僚に突っ込まれたので README も更新して、使い方を書きました。

Include-What-You-Use-CL

Include-What-You-Use-CL is Visual Studio toolset for Include-What-You-Use

Dependency

Include-What-You-Use

Install

git clone https://github.com/srz-zumix/include-what-you-use-cl.git
cd include-what-you-use-cl
install.bat

Usage

  1. Project Settings > Platform toolset
    Select "Include-What-You-Use" toolset
  2. Compile
  3. Get Include-What-You-Use result
    output

Uninstall

uninstall.bat

IWYU は cpplint にも組み込まれてたりするようなので、わざわざ cl から呼ぶ必要性はない気もしますが。。
お手軽に試せるので IWYU-CL も試してみてくださいmm

今回は以上です。
では。

2020年6月15日月曜日

[Visual Studio] .natvis/.natstepfilter をプロジェクトに追加してウォッチ・ステップインしやすくする

つい先日同僚からの情報で初めて知ったのですが、.natvis はプロジェクトに追加することでプロジェクト固有の Visualizer を設定できるようです。

.natvis って?という方は、過去に記事を書いているのでそちらを参照してください。

今まで Visual Studio 共有な形でインストールしていたので、プロジェクトごとに調整できるのは嬉しいですね!
また、.natvis は .pdb にも埋め込まれるようなので、起動した実行ファイルにアタッチしてデバッグ開始した場合でも、.pdb から .natvis を読み込んで適用されるようです。
(.pdb への埋め込みは設定で解除できます。詳細は最初のリンクへ)

iutest.natvis の例
.natvis がどのようなものか簡単に iutest が用意している .natvis で見てみたいと思います。(iutest は自作の C++ テスティングフレームワークです)

.natvis ファイルは以下。
  
<?xml version="1.0" encoding="utf-8"?>
<autovisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
  <type name="iutest::Test">
    <displaystring>{{ name={test_info_-&gt;m_testname}}}</displaystring>
    <expand>
      <item name="TestName">test_info_-&gt;m_testname</item>
      <item name="TestCaseName">test_info_-&gt;m_testcase-&gt;m_test_case-&gt;m_testcase_name</item>
      <item name="Results">test_info_-&gt;m_test_result</item>
    </expand>
  </type>
</autovisualizer>

これを読み込んでテストでブレークすると以下のように表示されます。


未加工ビューを開くと .natvis 適用していない素の状態を確認できます。


このように iutest では、this から不要なものを取り除いて見やすくした値が確認できるようにしています。

CMake に .natvis を追加する
普通に .natvis を追加すれば ok 。
iutest では、MSVC の場合には add_executable に .natvis を追加しています。

function(iutest_add_executable name)
if (MSVC)
  add_executable(${name} ${ARGN} ${IUTEST_ROOT_DIR}/tools/VisualStudio/Visualizers/iutest.natvis)
else()
  add_executable(${name} ${ARGN})
endif()
endfunction()
.natstepfilter はどうなのか?
Visual Studio の Visualizer にはステップフィルターもあります。
(Visualizer なのかな?って気がしてるが Visualizers ディレクトリに配置するのでそう呼んでる)
ステップフィルターについてはこちらも参考にしてください。

結論から書くと「まだできません」。要望が上がってはいます。

↑のブログでも書きましたが、GetInstance とかプロジェクト固有でステップインしたくないものって結構あると思うんですよね。
.natvis はグローバルにインストールされていても無害なことが多いと思いますが、ステップフィルターは条件をしっかり書かないと、他のプロジェクトのデバッグを阻害することになりかねないですからね。。
今後対応されることを期待します。

それでももう少し楽にできないか
現時点では、公式ドキュメントにかかれているとおりに、Visualizers フォルダにコピーして使うことになります。

チームメンバーに .natstepfilter を 「%USERPROFILE%\My Documents\<Visual Studio のバージョン>\Visualizers」 フォルダーにコピーして使ってというのも手間なんで、カスタムビルドルールで勝手にインストールされるようにしてみました。

.natstepfilter ファイルをプロジェクトに追加したら、ファイルのプロパティを開いて、項目を「カスタムビルドツール」にしビルドから除外を「いいえ」にします。
カスタムビルドツールの設定は、コマンドラインに「xcopy /I /Y "%(FullPath)" "$(VisualStudioDir)\Visualizers\"」を設定、出力ファイルを「$(VisualStudioDir)\Visualizers\%(Filename)%(Extension)」に設定します。

この状態でビルドをすると、.natstepfilter ファイルが Visualizers フォルダにコピーされ、デバッグ実行時にはコピーされた .natstepfilter がロードされます。
おまけ

std::string を s8 (UTF-8)表示する .natvis






2020年6月2日火曜日

Windows Performance Analayzer で C++ ビルド時間のプロファイルをしてみよう!


最近 clang の -ftime-trace オプションと chrome://tracing を使ってビルド時間の可視化をしてみましたが、Microsoft が提供している WPA(Windows Performance Analyzer | Microsoft Docs)も便利そうということで試してみました。


使い方
セットアップ
使い方は↑のツイートのリンク先ブログにも記載されています。

必要なのは VS2019 と Windows ADK です。
リンク先からダウンロードしてインストールしてください。
VS2019 では Community Edition でも問題なくプロファイリングできます。

次に VS2019 のインストールディレクトリから perf_msvcbuildinsights.dll を ADK のインストールディレクトリにコピーします。

「C:\Program Files (x86)\Microsoft Visual Studio\2019\{Edition}\VC\Tools\MSVC\{Version}\bin\Hostx64\x64」
→「C:\Program Files (x86)\Windows Kits\10\Windows Performance Toolkit」

(Visual Studio の方のパスは環境によって変わるので適宜変更してください。筆者環境では「C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\bin\Hostx64\x64」でした)
筆者が試したときは、ADK インストールディレクトリにすでに同名ファイルがありましたので、バックアップを取ってコピーしました。


このコピーをしておかないと C++ Build Insights (Template instantiations や Files)が見られないので注意してください。

トレース
準備が整ったらプロファイルを取得してみましょう。
こちらもブログの手順のとおりに行えば ok です。

まずは、「x64 Native Tools Command Prompt for VS 2019」を管理者権限で起動します。(vcvarsall.bat などから環境セットアップしたプロセスでも ok)


vcperf /start /level3 name

でトレースを開始します。
開始できたら、普通に Visual Studio でビルドしてください。(IDE からでもコマンドからでもどちらでも ok)

ビルドが終わったら vcperf を停止させます。このとき出力ファイルを指定します。

vcperf /stop /templates name output.etl


WPA で表示する
etl ファイルができたら WPA で表示してみましょう。
etl ファイルをダブルクリックすれば WPA が起動します。
ローディングが終わると以下のように表示されます。


あとは、Diagnostics から項目を選んでいけばビルドで何にどれだけ時間がかかっているのかが確認できます。



CircleCI で vcperf
ローカル環境でプロファイルを取得することもできますが、面倒なので CI でやるようにしてみました。今回使用した CI サービスは CircleCI です。
ターゲットとなるのはおなじみ「自作 C++ テスティングフレームワーク」の iutest です。

CircleCI を選択した理由は、すでに -ftime-trace の結果を CircleCI の成果物として保存するようにしていたので、vcperf の成果物も CircleCI に置こうと思ったからです。
それ以外の理由は特にありません。VS2019 がインストールされている Windows エージェントが使用可能なサービスであれば他でも問題ないと思います。(AppVeyor, Azure Pipelines, GitHub Actions, ...)
(※ CI-Spec で調査)

config.yml と計測用に追加したバッチファイルがこちら。
orbs:
  win: circleci/windows@2.2.0

jobs:
  vcperf:
    executor: win/default
    environment:
      CMAKE_GENERATOR_NAME: "Visual Studio 16 2019"
      CMAKE: "C:/CMake/bin/cmake.exe"
    steps:
      - checkout
      - run:
          name: install
          command: |
            $ProgressPreference = "SilentlyContinue"
            Invoke-WebRequest -URI https://github.com/Kitware/CMake/releases/download/v3.16.4/cmake-3.16.4-win64-x64.zip -OutFile $Env:HOMEPATH\cmake-3.16.4-win64-x64.zip
            Expand-Archive $Env:HOMEPATH\cmake-3.16.4-win64-x64.zip -DestinationPath "C:\"
            Rename-Item "C:\cmake-3.16.4-win64-x64" -NewName CMake
      - run:
          name: cmake
          shell: bash.exe
          command: |
            mkdir build && cd build && ${CMAKE} ../projects/cmake -G "${CMAKE_GENERATOR_NAME}" -A x64
      - run:
          name: vcperf
          shell: cmd.exe
          command: .circleci\vcperf_build.bat
      - store_artifacts:
          path: .\iutest.etl    
    call tools\VisualStudio\vcperf.bat /start /level3 iutest
%CMAKE% --build .\build
call tools\VisualStudio\vcperf.bat /stop /templates iutest iutest.etl

計測用にバッチファイルを別途用意しているのは config.yml の command で1つずつ処理しようとしたら vcvarsall.bat の exit 0 で処理が止まってしまったからです。
vcvarsall は vcperf.bat から呼び出されるようになってます。
もっと良い解決方法あれば教えて下さいmm

このジョブが完了すると Artifacts に iutest.etl がアップロードされています。
ダウンロードして WPA で確認してみましょう。

iutest のプロファイルを見てみる
では CircleCI で取得した etl ファイルを見てみましょう。

Build Explorer
まずは「Build Explorer」の結果↑
どのような処理がどのくらい時間がかかったかがわかります。
1ファイルのコンパイルにおいてどのようなことをしているのかも詳細に確認することができます。

Files
次に「Files」です↑
こちらは各ファイルの処理にどれだけ時間がかかったかがわかります。
また呼び出された回数もわかるので、Count が多いファイルは無駄に include されていないか確認すると良いかもしれません。

↑のようにファイルを展開すると、どこから include されたかどうかが1つずつ確認することができます。

Template Instantiations
最後に「Template Instantiations」です↑
こちらでは template の実体化にかかった時間がわかります。

デフォルトでは「Primary Template Name」が Visible になっているので、 すべての引数パターンが template クラス・関数名でまとめて表示されています。
こちらの Visible のチェックを外すと template 引数違いで時間順に並べられます。
これでボトルネックになっている template の実体化が見つけやすくなると思います。

また検索機能を使うことで、↓のように特定の名前に絞って表示することもできます。

Specialization Names のノードを開くと、どこから実体化されたかもわかるようになってます。

改善ポイント
さて、iutest に絞り込んだ場合 iuCsvFileParamsGenerator<float> の実体化がトップでした。
しかしながら、この iuCsvFileParamsGenerator は CSV ファイルからテストパラメータを読み込ませるときにしか実体化されない想定でした。
上記の2枚目の画像を見ていただくと、Count が 155 回記録されています。
今回記録したときのビルドでは複数のテストをビルドしていますので、おそらくテストの数(exe の数)だけ実体化されていそうです。

使うときにだけ実体化されるのが理想なので、詳細を追ってみたところ、iuCsvFileParamsGenerator<float>::ToParam の特殊化がありました。

おそらく、これが原因でしょう。
今回の記事はここまでですが、この修正結果については Twitter かブログで報告したいと思います。

最後に
WPA はプラットフォームは限られますが、clang -ftime-trace + chrome://tracing でプロファイルするよりも、ビルド時間のボトルネックになりやすい Template Instantiation を調べやすくていい感じだなと思いました。
セットアップや使い方も簡単なのでぜひやってみてください。

では。

追記(2020/06/15)

iuCsvFileParamsGenerator の特殊化をなくして、もっと低レベルでの特殊化(クラス外に追い出した)ところワーストから消えてることを確認しました。

今回の計測前後の etl ファイルをこちらに置いておいたので興味がある方は分析してみてください。


2020年1月28日火曜日

Visual Studio のプロジェクト設定は共通部分を前に書こう

Visual Studio で複数の構成を扱っている場合がほとんどだと思います。
Debug/Release、Win32/x64 などなど。
MD/MT とかもありますね。dll/static lib とかもあるか。

それぞれ、インクルードパスだったり、プリプロセッサ定義だったりを書くと思いますが、私からのお願いです。

「各構成で共通な設定を先頭に書いてください」
「専用の設定を末尾に書いてください」


なぜか
Visual Studio で設定を編集する場合に、個々の構成に対して編集ができますが、
すべて・もしくは任意の複数構成で編集することもできるからです。
複数構成の編集をする場合、以下のように共通部分がそれぞれ表示されます。
差分があると「<別のオプション>」のように表示されます。

例:
Platformプリプロセッサの定義
Win32WIN32;_DEBUG;_LIB;
x64WIN64;WIN32;_DEBUG;_LIB;

Win32

x64

すべてのプラットフォーム


わかりますよね?
差分が先頭にあると、すべて「<別のオプション>」になってしまうのです。


共通部分を先頭に書く
共通部分を先頭にまとめておけば、複数構成で編集・閲覧するときに圧倒的に楽です!!
先程の例を修正してみましょう。

Platformプリプロセッサの定義
Win32WIN32;_DEBUG;_LIB;
x64WIN32;_DEBUG;_LIB;WIN64;

Win32 はそのまま、x64 の WIN64 を末尾に移動しました。

Win32

x64

すべてのプラットフォーム


いかがでしょうか?
差分を末尾に移動するだけで、こんなにも見やすくなりました。


もちろん、この状態で編集しても差分部分が壊れることはありません。


こちらは Visual Studio 2015 で試したものです。最新のバージョンでも同様です。
以上、私からのお願いでした。


P.S.
技術書典の進捗報告予定でしたが、カッとなって書いた。
技術書典の方は、執筆しつつも、今週はサークルカットを準備するのにほとんど時間を使ってました・・

では、また来週。

2019年7月16日火曜日

[Visual Studio] ステップフィルターのカスタマイズでデバッグを楽にする

かなり前に Visualizer を紹介しましたが、今回はステップフィルターの紹介をします。
「ブログズミ: [Visual Studio] デバッガー変数表示のカスタマイズ」

Visual Studio ではステップインする際に、
特定の関数には入っていかないようにする設定がユーザー定義でできるようになっています。
Customize C++ stepping behavior independent of Just My Code settings

それを設定して何が便利なのか?
よくある事例で見てみましょう。

まずは設定なし。

そして、設定あり。


どちらも UnitTestSource::GetInstance().Initialize(); の Initialize にステップインしようとしている様子です。
いかがでしょう?
前者のように GetInstance にいちいちステップインしちゃうのが煩わしく感じてる人は多いのではないでしょうか?

ステップフィルターを設定した後者は GetInstance() の中に入っていかなかったですね。
このように、1行に複数の関数呼び出しがある場合に、興味がない関数へのステップインをしないようにするとデバッグがしやすくなると思います。

今回紹介する .natstepfilter を使って、この煩わしさから開放されましょう!


設定の仕方
.natstepfilter 拡張子のファイルを作成し、
「%VsInstallDirectory%\Common7\Packages\Debugger\Visualizers」もしくは「%USERPROFILE%\My Documents\\Visualizers」に保存するだけです。

ファイルのフォーマットは xml になっています。
この xml で関数の指定とその関数に対して、ステップインするか、しないかの設定を行います。
以下は GetInstance にステップインしないようにする .natstepfilter の例です。

<Function>
        <Name>iutest::.*GetInstance.*</Name>
        <Action>NoStepInto</Action>
    </Function>

.natstepfilter は複数のファイルに分けて書くことができますので、stl.natstepfiler と iutest.natstepfilter のように namespace や用途に合わせて分けておくと便利だと思います。



iutest の例
さて、上記で iutest での GetInstance の事例を紹介しましたが、
iutest では、テスティングフレームワークの利用者はフレームワークの内部実装には興味がなく、テストコードにのみ興味があるはずという考えのもと、テストコードから内部実装にステップインしないようにした natstepfilter を提供しています。

<?xml version="1.0" encoding="utf-8"?>  
<StepFilter xmlns="http://schemas.microsoft.com/vstudio/debugger/natstepfilter/2010">  
    <Function>
        <Name>iutest::TestEnv::environments</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::UnitTestSource::Run</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertionSuccess</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertionFailure</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertionResult.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertionHelper.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertPred.*Helper.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::PrintToString.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::WithParamInterface.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::.*GetInstance.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::Test::RecordProperty.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::UnitTestImpl::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::detail::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iuutil::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::matchers.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::internal::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>std::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
</StepFilter>

ユーザーが集中したいコードにのみ、ステップインするのでテストコードのデバッグがしやすくなったのではないか、と思ってます。

Resharper C++ をインストールしていると利用できない
https://pleiades.io/help/resharper/Reference_Options_Tools_Debugger_CPP.html
Resharper C++ にステップフィルターの機能があるため、すべてそちらの管理になります。
そのため、.natstepfilter の設定は引き継がれません。(継承かインポートできると嬉しいですが・・・)

Resharper 使っている方はご注意くださいmm


最後に
Visual Studio は "知っていれば" 便利な機能が結構あります。
ツールは使ってなんぼ。ただ使ってるだけじゃもったいないです。

これまでもいくつか機能を紹介してきましたが、今後も Visual Studio にはお世話になると思うので、また便利な機能を知ったら紹介したいと思います。

では。

2018年4月17日火曜日

[MSVC] pragma warning での警告抑止はどこにでも書けばいいというものではなかった [2013]

Visual Studio 2013 なんてもう誰も使ってない気がしますが
Visual Studio 2013 で pragma warning による警告抑止が効かないケースがあったので、メモです。

気づいたのは、iutest で MSVC の警告撲滅をしていたのがきっかけです。

問題のコードはこちら
https://github.com/srz-zumix/iutest/blob/6a2a798458aa220f2d1a88b8a79be39a867e8709/include/internal/iutest_port.hpp#L283

template
class IUStreamBuffer
{
public:
    // __pragma(warning (push))
    // __pragma(warning (disable: 4996))
    IUTEST_PRAGMA_CRT_SECURE_WARN_DISABLE_BEGIN()

    explicit IUStreamBuffer(FILE* fp)
        : m_fp(fp)
    {
        m_buf[0] = '\0';
        fflush(fp);
        setvbuf(fp, m_buf, _IOFBF, SIZE);
    }

    ~IUStreamBuffer()
    {
        fflush(m_fp);
        setbuf(m_fp, NULL);
    }

    // __pragma(warning (pop))
    IUTEST_PRAGMA_CRT_SECURE_WARN_DISABLE_END()
setbuf が C4996 出るので pragma warning push/disble/pop をつけていました。
VS2017 や VS2015 では上記の書き方で問題がなかったのですが、Visual Studio 2013 では正しく警告抑止ができてませんでした。



template
class IUStreamBuffer
{
public:
    explicit IUStreamBuffer(FILE* fp)
        : m_fp(fp)
    {
        m_buf[0] = '\0';
        fflush(fp);
        setvbuf(fp, m_buf, _IOFBF, SIZE);
    }

    ~IUStreamBuffer()
    {
    // __pragma(warning (push))
    // __pragma(warning (disable: 4996))
    IUTEST_PRAGMA_CRT_SECURE_WARN_DISABLE_BEGIN()
        fflush(m_fp);
        setbuf(m_fp, NULL);
    // __pragma(warning (pop))
    IUTEST_PRAGMA_CRT_SECURE_WARN_DISABLE_END()
    }


こうだとちゃんと警告が抑止されたので、どうやら書く場所が悪かったみたいです。
(今は setvbuf 使うようにして抑止しなくていいようにしたので、上記コードはなくなりました)


まとめ
最新のコンパイラーなら大丈夫なのかもしれませんが、pragmra warning はどこにでも書けるという認識が間違っていた、というのは良い収穫でした。
極力、警告抑止はない方がいいですが、使う場合はなるべく小さなスコープで書くようにしたいと思います。


今回は以上です。では。

2017年6月19日月曜日

[Visual Studio 2017] インデント問題を解決する? .editorconfig を使ってみた

Visual Studio 2017 からプラグインインストール不要で EditorConfig が使えるようになったので、遅ればせながら使ってみました。
2017 のリリース直後に試して、ブログにしようと思ってましたが、なんだかんだでこの時期になってしまいました。
なので、特に"これ"という情報はありません(;´・ω・)。が、editorconfig 便利だなーということだけ紹介します。

EditorConfig とは?
EditorConfig はインデントのタブ派 vs スペース派などのルールを書式化し、個人のエディタ設定によらず、コーディングスタイルの統一ができるようになるものです。


チーム内のスタイル統一が容易になるのもメリットですが、個人的には1つのエディタでプロジェクトごとの設定を意識せずにコーディングできるとこが便利だなーと思いました。

Visual Studio の場合ですと、インデントの設定はグローバルに1つだけなので、タブ派なプロジェクトとスペース派なプロジェクトを跨いで作業するのは大変でした。
これが、Visual Studio 2017 から EditorConfig が使えるようになったので、とっても捗ります!
(※ 2017 以前でも拡張機能をインストールすることで使用できます)

iutest の .editorconfig
root = true
 
 [*]
 indent_style = space
 indent_size = 4
 insert_final_newline = true
 
 [Makefile]
 indent_style = tab
 
 [*.{cpp,hpp,ipp}}
 charset = utf-8-bom
 
 [*.py]
 charset = utf-8
 
 [*.{yml,html}]
 indent_size = 2

これをルートディレクトリに配置するだけで、Visual Studio が自動的に設定を読み込んで、インデントなど指定した通りに編集できるようになります。

設定できる項目
公式にまとまっているので、そちらを参照してください。

https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties




editorconfig、本当に便利なんで、会社でもリポジトリに突っ込んでいこうと思いました。
今回は以上です。ではでは。

2017年5月29日月曜日

[Visual Studio] 1行の文字数制限のガイドラインを表示する

cpplint とかでよく1行あたりの文字数に対してい警告が出たりしますよね?
プロジェクトによっては、"厳守" であったり、"できるだけ対応" であったり、ルールが違うと思います。

これ、lint にかける前に意識してコーディングしたいな~と思いました。
自分の場合、厳しいルールの環境ではなかったので、強制的に改行するようなものではなく、
ガイドライン引けるものがないか探して見たところ、ドンピシャなものがあったので紹介します。


Editor Guidelines
Editor Guidelines 拡張機能を使います。


これをインストールすると、エディタの右クリックメニューに「Guidelines」が追加されます。

「Add Guideline」をクリックすると、このようにガイドラインが表示されます。



短い!!


ということで、
文字数を指定する場合は、「コマンドウィンドウ」を開いて以下のコマンドを打ち込みます。
(既に Add してると失敗するので、Remove しておいてください)

Edit.AddGuideline 100




これで、任意の文字数のところにガイドラインが引けました!


ちょっとしたことですが、これでまた Visual Studio が便利になりました~
ではでは。