Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CMake 3.8.0以降のCTestの文字化け対策 #37

Closed
yossi-tahara opened this issue Jun 15, 2017 · 5 comments
Closed

CMake 3.8.0以降のCTestの文字化け対策 #37

yossi-tahara opened this issue Jun 15, 2017 · 5 comments

Comments

@yossi-tahara
Copy link
Owner

Issue #16 からの分岐です。

CMake 3.8.0でCTestに次の修正が入りました。

  • 子プロセスの出力をUTF-8のみ受け付ける

恐らくそれが原因で、Theolizerにより生成されたアプリのビルド・テストが文字化けするようになりました。コンパイラのエラー・メッセージが全く読めないので、非常に痛いです。

このIssueでこの問題に対処します。

@yossi-tahara
Copy link
Owner Author

yossi-tahara commented Jun 15, 2017

この件、回答を頂けました。ポイントは下記と理解しました。

  • CTestが受け取る文字コードをexecute_processで制御し、UTF-8にして下さい。
  • CTestはバイプとファイルへはUTF-8で出力します。

私も今日一日現象を調査し、上記結論にまでは達したところでした。
(また、CTestはコンソール出力時はコンソールのコードページへ変換するようです。)

CTestのテスト対象からの出力のUTF-8への変換は、execute_process用cmakeスクリプトを追加することで対応できました。
しかし、残念ながら、まだ化けます。上記のCTestがUTF-8でパイプへ出力することが原因のようです。

現在、下記のようなCMakeLists.txtでビルドとテストを1コマンドで処理できるようにしています。

add_executable(build_target ...)
add_custom_target(LongTest COMMAND "ctest" "-V" "-C" "$<CONFIG>" "-L" "Test.*L.*")
add_dependencies(LongTest build_target)
cmake --build . --target LongTest  

テストはビルドの一部と思いますし、テスト前にビルド漏れしたくなかったので、このようにしました。

cmake --build .でMSBuildが起動され、MSBuildはctest -V -C $<CONFIG> -L Test.*L.*を起動し、その出力をパイプで得ていると思われます。
MSBuildは恐らくCP932を期待しています。しかし、ctestはUTF-8で出力します。このミスマッチが原因だろうと思うのですが、ctestの出力の日本語が一部壊れます。
そして、更に、MSBuildはCP932でメッセージを出力するのでctestのUTF-8出力と入り混じります。

CMake 3.8.0のCTestの修正は、これです。
子プロセスの文字列をUTF-8であると決めつけたのですね。execute_processを介してそのようにしなさいと言うことのようです。

そして、UTF-8と決めることができたので、冒頭の制御が行われるようです。

  • バイプとファイルへUTF-8で出力する
  • コンソールへCP932(コンソールのコード・ページ)で出力する

MSBuildとcmake --build

MSBuildは起動前にchcp 65001としておけばUTF-8で日本語出力するし、chcp 437としておけば英語で出力します。ただし、他に英語で出力させる方法が見つかっていません。少なくとも公開されているパラメータにはないようです。

さて、cmake --buildはMSBuildを起動するのですが、その時、コンソールのコードページをCP932へ設定します。cmake --build前にchcp 65001などしていてもCP932になります。
恐らくGetACP()で受け取ったシステムのコードページを設定しているのだろうと思います。
chcp 65001して全てをUTF-8で制御できればと思ったのですが、このcmakeの働きのため、それも無理です。
せめて英語出力にできれば良いのですが、コードページを変更する以外の方法が見つかっておらず、こちらも厳しいです。

対策案

従って、CTestをMSBuildで起動する限り回避することは困難です。
ですので、LongTestターゲットでテストを起動することを断念するしかありません。

テストはスクリプトからも起動できるので、cmakeスクリプトで起動する方向で進めたいと思います。CMakeのバージョンを問わず機能する筈ですので、これでうまく行けばこの方法を採用します。
今にして思えば、頑張ってCMakeに組み込むのではなく、スクリプトで起動しても良かったなと思います。

@yossi-tahara
Copy link
Owner Author

ビルド部とテスト部をzz_process.cmakeから別途起動し、前者はENCODING AUTO、後者はENCODING無しとすることで、CMake 2.8.0以降の場合、ビルド・ログをUTF-8にしてビルド・ログ内の文字化けを回避できました。
しかし、サマリーをコマンド・プロンプトへ出力するのですが、その際に文字化けします。
CMakeでUTF-8からCP932へ変換する方法を探しているところです。

yossi-tahara added a commit that referenced this issue Jun 16, 2017
  Windows上のそれ以前のCMakeではShift-JISのままとなる。
  ただし、msvcは3.8.0以上を必須指定する予定。

------ auto generated message by Theolizer
TheolizerDriver  : 3f39873d1a0b72b3b678d55526786951
TheolizerLibrary : f895eff9401937bccebc76ddbd100ccf
Library's Header : 373c3c8571f1a3a5145eb82c9d090106
------ end of message
@yossi-tahara
Copy link
Owner Author

サマリーをコマンド・プロンプトへ出力するのですが、その際に文字化けします。

この問題は、コマンド・プロンプトで、chcp 65001 コマンドを発行してUTF-8表示に切り替えることにしました。

そして、ビルド部とテスト部の分離については下記仕様で進めており、概ね完成しました。

  • WindowsではCMake 3.8.0以降を必須とし、UTF-8にてログ出力(従来はShift-JIS)
  • ubuntsuはCMakeバージョンは従来通りとし、従来と同じくUTF-8でログ出力

この内容でローカル環境(Windowsとubuntu)ではビルドとテストに通っています。
しかし、travis-ciでテストすると通りません。travis-ciの問題は Issue #38 とします。

yossi-tahara added a commit that referenced this issue Jun 20, 2017
  CTestから呼び出すテストを全てexecute_process.cmake経由とし、
  CMake 3.8.0以降なら、execute_process( ... ENCODING AUTO)指定するようにした。

  また、build_toolsのビルド・スクリプトでCMAKE_VERSIONが正規シンボルにかぶっていたので変更。
------ auto generated message by Theolizer
TheolizerDriver  : 7d797894e7caf24953369055bafe1146
TheolizerLibrary : 2dd140e84964ed482d476b0e4135424b
Library's Header : 373c3c8571f1a3a5145eb82c9d090106
------ end of message
yossi-tahara added a commit that referenced this issue Jun 20, 2017
------ auto generated message by Theolizer
auto test(one-set) : PASS
TheolizerDriver  : 8785e0775e4e7678c4b57dd74b4eedaf
TheolizerLibrary : 507d60fb6e940b7a4c51261cb7525f32
Library's Header : 373c3c8571f1a3a5145eb82c9d090106
------ end of message
@yossi-tahara
Copy link
Owner Author

この件、対応しました。

CMake 3.8.0にて、Windows向けのCTestの仕様が以下のように変更されています。(linuxには影響しないようです。)

  • CTestが起動する子プロセスの出力はUTF-8のみ適切に受け取れる・・・①
    もし、Shift-JIS等でエンコードされた日本語文字列を渡すと文字化けする。

  • CTestの出力は、
    コマンド・プロンプトには、コマンド・プロンフトのコードページ(日本語WindowsならShift-JIS=CP932)へ変換して出力。
    バイプとファイルには、UTF-8で出力する。・・・②

この①と②が頭痛いです。特に②の結果文字化けしないようにするため使い勝手が少し劣化します。

①の対処

これは頂いたアドバスを参考に、add_test()で直接テスト対象を起動するのではなく、execute_process.cmakeスクリプトを起動し、その中で、excute_process( ... ENCODING AUTO)でテスト対象を起動するようにしました。
これにより、テスト対象がCP932で出力しても、それをexcute_process( ... ENCODING AUTO)がUTF-8へ変換するため、ここでの文字化けを回避できます。

②の対処

リダイレクトせずにビルドする場合は問題ありません。CMakeによるビルド結果はCP932で出力され、CTestの出力もCP932ですので。
問題はそれをファイルにリダイレクトした時です。前者はCP932で出力され、後者はUTF-8で出力されます。

この2つをbatを使って1コマンドで起動したい人は頭が痛いことになります。
(CMakeの該当Issueには報告しました。)

Theolizerのビルド・システムはビルドとテストを1コマンドで実行するため、上記に該当します。
対処としては、CTestの出力をC932へ変換する場合は、別ツールを導入するか、変換ツールを作るしかありません。
ビルド・システムはできるだけ依存性を低く保ちたいのて、前者はできれば避けたいです。後者は手間がかかるのでやはりできるだけ避けたいです。

そこで、CTestの出力をCP932へ変換することは断念し、ビルド・メッセージをUTF-8へ変換することにしました。
もともとexecute_processで起動しているので、そこにENCODING AUTOを追加しました。
単純に追加すると、gccや,mingwの時もCMakeを3.8.0以上へアップデートする必要が出てくるため、Visual Studioのケースでのみ追加するようにしています。

また、サマリーを一旦ファイルへ保存し、最後に表示しています。上記理由でサマリーはUTF-8で記録されるため、そのまま出力すると文字化けします。
そこで、ビルドを起動し最後にサマリーを出力するzz0_full_all.bat、zz1_short_test.bat、zz2_long_test.bat、zz3_full_test.bat、zz4_ja.batについては、chcp 65001することでコマンド・プロンフトをUTF-8モードに切り替え、文字化けを回避しました。
(なお、エラー・メッセージは一部しか表示していないため、文字の途中で途切れるとその文字が化けますが、この対処は断念しました。)

@yossi-tahara
Copy link
Owner Author

問題なさそうですので、クローズします。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant