窓を作っては壊していた人のブログ

提督の窓や成績の窓を作ってました.今では適当に好き勝手に開発をしてます.

日本語を含むC++のプロジェクトをAppVeyorでビルドしたらはまった

Raspberry Piに喋らせてみるみたいなことで使ってる人もいるのかもしれない OpenJTalk. これをC# でラップして,ライブラリ化して使いたいなと思ったためちょこちょこと作業をしていました.

実際のC/C++のプロジェクトがこちら

GitHub - yamachu/LibOpenJTalk: Unofficial OpenJTalk mirror

そして成果物のC# ラッパーがこちら

github.com

以前このブログでも紹介したように各プラットフォームでネイティブのライブラリをビルドし,DllImport属性などを使ってラップしていくやり方で行っていたのですが,どうもWindows環境で日本語をネイティブ側に渡そうとすると文字コードの問題が発生してしまうと言った問題が起こりました.

結論としてはAppVeyorの言語ロケールが英語になっていたため,ソースコードUTF-8で保存されたものと解釈しそのままビルドが行われたりしたことが問題でした. またコマンドラインオプションを使用しないとビルドすら通らなかったため,AppVeyorでビルドする際はそのあたりも考えたほうが良かったみたいです.

まずはビルドを通るようにするには,cl.exe のオプションに対象ソースコード文字コードを記述します. 自分はSJISで保存されたファイルだったので /source-charset:.932 を追記しました.

こちらの記事が非常に参考になりました.

Visual C++(cl.exe)で UTF-8 のファイルをコンパイルする - Bite Code

この修正によりビルドが通るようになりましたが,複数のwarningが発生し,また生成されたライブラリで日本語の扱いがうまくいかないバグが発生しました. 実際の warning は以下のとおりです.

c:\projects\libopenjtalk\text2mecab\text2mecab_rule_shift_jis.h(75): warning C4566: character represented by universal-character-name '\u3000' cannot be represented in the current code page (1252)

ここの 1252 は Windows-1252 - Wikipedia のことを指します.

どうもロケールを変えてcode pageを今回ではSJISの932に変えてあげる必要がありそうです.

やり方は流石にAppVeyorとかのドキュメントに書いてあるだろうと思ったのですが,実際載ってなくてIssueを漁っていたら発見できました.

Support a different code page · Issue #846 · appveyor/ci · GitHub

日本語環境では

init:
- ps: Set-WinSystemLocale ja-JP
- ps: Start-Sleep -s 5
- ps: Restart-Computer

こんな感じです. ちなみにこのStart-Sleepを抜くと処理が返ってきません(このCIを回して他の作業をしていたのですが通知がこなくて見てみたら止まっていましたw)

こんな感じで日本語を含むプロジェクトでもAppVeyorでいい感じにビルドできそうです.

このミスに気づくのに数日かかったの本当に辛いお気持ちです…