おがさわらなるひこのオープンソースとかプログラミングとか印刷技術とか

おがさわらなるひこ @naru0ga が技術系で興味を持ったりなんだりしたことをたまーに書くブログです。最近はてなダイアリー放置しすぎて記事書くたびにはてな記法忘れるのではてなブログに移行しました。

クリエイティブ・コモンズ・ライセンス
特に断りがない場合は、本ブログの筆者によるコンテンツは クリエイティブ・コモンズ 表示 - 継承 4.0 国際 ライセンスの下に提供されています。

短期集中連載? LibreOfficeをWindowsで開発してみよう:その⑤ 不具合直して? みたよ

GWの間にLibO開発できる環境をWindowsで作ろうの連載5回目。さてGWやらも本日で終わり、なのでこの短期集中連載もさしあたりの最終回。

過去記事:第1回 第2回 第3回 第4回

せっかく開発環境作ったのになんにも触らないのもアレなんで、適当なバグを直してみようと。ターゲットにしたのはこれ。

bugs.documentfoundation.org

この不具合なんですが、平たく言うとExcelで作成した「セルの書式設定で大字(12345……を壱弐参四五……って書くやつ)を指定したセルが、LibO Calcで開くと大字にならないってものです。

Excelで大字表示ってどうやるんだろ……って調べてみると、たとえばこのサイトがヒットしたんですけど:

www.kenzo30.com

書式記号に [DBNum2] って指定すればいいらしいです。

Excelの書式指定子(Modifier)、Calcでも指定できるので指定してみる……と、

f:id:naruoga:20200506210339p:plain
書式指定子 [DBNum2] 指定

ホントだ。大字にならないですね。ということでこれを追ってみることにします*1

ソースを検索して該当部分を探す

最初はやみくもにソースを検索して該当部分を探してみましょう*2

ソースの検索は OpenGrok でも git grep でもよいですが、まあせっかくなのでVS2019上で検索してみることにします。 Ctrl-Shift-F を押してソリューション内検索ダイアログを開いて "DBNum2" を検索します。

見つかったのはテストコード、コメントを除くと /svl/source/numbers/zformat.cxx だけ。名前からいってもそれっぽい。ということで中を覗いてみます。

デバッガを使いつつなんとなく眺める

パッと目に入るのは、 SvNumberformat のコンストラクタ。 こいつもまあ相当長いメソッドなのですが、要は書式指定子の文字列をパースして [DBNum2] なら 2 を取り出して保持しておく処理っぽいですね。

あと DBNum というキーワードでなんとなくコードを眺めると:

sal_uInt8 SvNumberNatNum::MapDBNumToNatNum( sal_uInt8 nDBNum, LanguageType eLang, bool bDate )
sal_uInt8 SvNumberNatNum::MapNatNumToDBNum( sal_uInt8 nNatNum, LanguageType eLang, bool bDate )

というペアのメソッドが目につきます。なにやら内部的に DBNum と NatNum なるものを相互に読み替えているらしい。 試しにデバッガで前者にブレークポイント設定して*3 DBNum2 を設定してみたら呼ばれてますね。なるほど。 私はこんな風にブレークポイントしかけて確かにこれが見るべき処理かって確認するのよくやります。 机上で追い込むの苦手なので……。

そこで、おっと思ったのが、さっきのテストでセルの書式設定に [DBNum2] とやったやつ。 あれを保存して再度読み込みなおすと、 [NatNum4] という書式指定に代わってしまう。

f:id:naruoga:20200506215618p:plain
書式指定が変わってしまう

ここでようやっと、仕様確認しようと思いつきました(遅い)。ヘルプを "DBNum2" で検索すると、このページがヒットしました。

help.libreoffice.org

「Displaying Numbers Using Native Characters」とあるとおり、NatNum というのはNative Numberなんでしょうね。 LibOの書式指定のネイティブはこっち。

で、Excel(OOXML)からインポートしたり、手打ちで書式指定 DBNum2 とかした場合は、適切なNatNumに変換して内部的にはそれを使って処理する……と。なるほどね。 エクスポートするときには逆に NatNum から DBNum に書き戻すのでしょう。

さてヘルプを見ると、…… DBNum2NatNum4 に対応するということですね。 それは、ODSで保存して読み込み直すときの結果と符合しますね。なのでここに間違いはないと*4

じゃあそうなると、書式指定をもとに実際の表示文字列を組み立てるところ、それが問題あるということでしょうか。 表示文字列を組み立てるところ、それって多分ですけど、普通の実装なら、 セルの内容を渡したら文字列が返ってくるメソッドを用意するんじゃないでしょうかね*5

ということで、ソースコードgrepして(ここはVS2019使わないんかい!) zformat.cxx の中で戻り値が OUString なものをgrepして、中のぞいて、あーそれっぽいと思ったのがこの二つ。

OUString SvNumberformat::impTransliterateImpl(const OUString& rStr,
                                              const SvNumberNatNum& rNum ) const
{
    css::lang::Locale aLocale( LanguageTag( rNum.GetLang() ).getLocale() );
    return GetFormatter().GetNatNum()->getNativeNumberStringParams(rStr, aLocale, rNum.GetNatNum(),
                                                                   rNum.GetParams());
}

void SvNumberformat::impTransliterateImpl(OUStringBuffer& rStr,
                                          const SvNumberNatNum& rNum ) const
{
    css::lang::Locale aLocale( LanguageTag( rNum.GetLang() ).getLocale() );

    OUString sTemp(rStr.toString());
    sTemp = GetFormatter().GetNatNum()->getNativeNumberStringParams(
        sTemp, aLocale, rNum.GetNatNum(), rNum.GetParams());
    rStr = sTemp;
}

どっちも GetnativeNumberStringParams() なるメソッドを読んでるわけですが、ここはVS2019でステップ実行でステップインして飛びますと、 最終的には i18npool/source/nativenumber/nativenumbersupplier.cxxNativeNumberSupplierService::getNativeNumberString() メソッドに来るわけですね。

で、こいつをデバッグ実行しつつ追うと、

    switch (nNativeNumberMode)
    {
        ...
        case NativeNumberMode::NATNUM4: // Text, Lower, Long
            number = &natnum4[langnum];
            break;

という処理があって、ここで number という変数に入ってくるのは、すでに大字ではない通常の漢数字……ふむぅ。……ん?

ここで仕様(というかヘルプ)を再度確認

はい、私のよくなかったところ。 おもむろにソースを見る前に、「解くべき問題は果たして何か(何が正しいふるまいか)」を確認する必要がありましたね。

で、ヘルプ再度確認すると、いやー間抜け:

f:id:naruoga:20200506230700p:plain
NatNum4 は modern long Kanji text !

NatNum4 は modern だって書いてあるじゃー、ないですか!

なのでヘルプの記述が仕様として正しいなら、今の動作は完全に正しい。そして、古いヘルプ:

help.libreoffice.org

を見ると、この動作は3.3から……というかOpenOffice.orgのころから変わっていない、と思われます。

でもおかしいですよね、Excelでは DBNum2 は大字なのだとしたら、当然LibOではそれに対応する NatNum5 じゃないと、バグ起票されたようにExcelとの互換性がないということになってしまう。うーん。わからん。

目をつぶって直す

まあいいや、もし仮にこいつ直すとしたらどうするか。

結果としては DBNumXNatNunX の割り当てだけが問題ってことになったので、前述の:

sal_uInt8 SvNumberNatNum::MapDBNumToNatNum( sal_uInt8 nDBNum, LanguageType eLang, bool bDate )
sal_uInt8 SvNumberNatNum::MapNatNumToDBNum( sal_uInt8 nNatNum, LanguageType eLang, bool bDate )

この二つを直せばいいということになります。

本来ならすべてのマッピングを見直す方が適切なのかもわからないですが、さしあたりはこの問題だけ直してみます。 以下diffだけだと若干情報足りないので手で補った嘘diffです。

@@ -170,7 +170,7 @@ sal_uInt8 SvNumberNatNum::MapDBNumToNatNum( sal_uInt8 nDBNum, LanguageType eLang
          switch ( nDBNum )
          {
          ...
          case 2:
             if ( eLang == primary(LANGUAGE_CHINESE))
                 nNatNum = 5;
             else if ( eLang == primary(LANGUAGE_JAPANESE) )
-                nNatNum = 4;
+                nNatNum = 5;
             else if ( eLang == primary(LANGUAGE_KOREAN) )
                 nNatNum = 2;
             break;

こちらは DBNum2NatNum4 にして、

@@ -238,7 +238,7 @@ sal_uInt8 SvNumberNatNum::MapNatNumToDBNum( sal_uInt8 nNatNum, LanguageType eLan
          switch ( nNatNum )
          {
          ...
          case 4:
             if ( eLang == primary(LANGUAGE_CHINESE) )
                 nDBNum = 2;
             else if ( eLang == primary(LANGUAGE_JAPANESE) )
-                nDBNum = 3;
+                nDBNum = 2;
             break;
         case 6:
             if ( eLang == primary(LANGUAGE_CHINESE) )

こちらは逆に NatNum4DBNum2 に戻しているだけ。あー、超簡単だ。

で、この変更を入れてビルドしたやつで、バグ報告についてたファイルを開いてみると……。

f:id:naruoga:20200506233209p:plain
6.4だと大字になってない

f:id:naruoga:20200506233429p:plain
直したやつだとちゃんと大字になる

直ってますね!

もし……仮にもし、これをパッチに出すとすると、

  • まずはあるべき仕様を日本コミュニティで議論(メーリングリストかな?)。
  • 上記に基づき、DBNum2 以外に対する処理も書く。
  • ユニットテストでこの処理を確認しているものがあるげなので、直すなり、もしこのケースを確認してないなら追加するなりする。
  • ヘルプも直す。
  • コミット整えて、gerrit に push

ってな感じですかねー。

まあともかく、開発環境作ってリアルな問題を(少なくとも技術的には)解けるところまではいったので、 ゴールデンウイークとしてはまあまあの成果かな?

せっかくなので、これっきりにしないで定期的に開発にかかわっていきたいですね!

*1:なお調査しなくてもhimajin100000さんがコメントで書いてくださってるんですが、それはなんというか、練習なので、カンニングしない方向で……。

*2:慧眼なる読者の皆様ははこれが誤った手順であることにお気づきかと思います……。詳細はのちほど。

*3:個人的な言葉づかいで「ブレークポイントをはる」っていうんですが、この「はる」は張るなのか貼るなのかそれ以外なのか。

*4:もう気付いている人はいらっしゃると思いますがこれも伏線……です。

*5:引数で渡したオブジェクトの参照に値詰めて戻る実装もあるけど、文字列なら普通returnします……よね?

短期集中連載? LibreOfficeをWindowsで開発してみよう:その④ Visual Studio開発落穂ひろい

GWの間にLibO開発できる環境をWindowsで作ろうの連載4回目。環境作るだけじゃなくてできればバグつぶしてコミットするところまで行きたい。

過去記事:第1回 第2回 第3回

今日……というか昨日か、はあんまり進んでません。 なぜならSNSなどでご覧になった方はいるかもしれませんが、開発用のノートPCのHDDをSSDに換装したら、環境が全部ふっとんじゃったからです。 それを戻すのに時間がかかってこっちの作業あんまり進められませんでした。

なのでその際に気づいたメモなどを書いてお茶を濁します。 いちおうソースコード眺め始めてはいますが、まだ目立った成果はないので……

  • ディスク換装したのですが \cygwin\ 以下をまるっと古いディスクからコピーすればいいかと簡単に考えてましたがダメだったみたいです
    • git リポジトリでどうやってもuntracked changeがなくならない……
    • checkout -fcleanstash / stash drop もダメ
    • しょうがないので dev 以下捨てて lode 直下で ./setup --dev --force やり直して再ビルドしました
  • VS2019ソリューションが読めない
    • 言語パック切り替えるの忘れてたので English にしたら通りました
    • ただこれ、言語パック忘れじゃなくて、なにか VS Installer でちゃんとインストールできてなかったものがあって、 言語パック切り替えでそれがちゃんと入ったとかなのかも
    • 実は今回 workload の導入にも chocolatey 使ってみたんですけど、そいつが途中で刺さっちゃったんでアボートしたんですよね
      • ビルドとおったので大丈夫かな? と思ってたのですが、大丈夫じゃなかったのかも
  • デバッグ実行起動遅い話は、SSD化でだいぶ改善しました。やっぱり金の力は偉大だ

今はそんだけです。夜の報告でコードの解析結果とかお見せできたらいいな。

LibreOffice Asia Conference 2019 Tokyo 基調講演の紹介

去年行われましたLibreOffice Asia Conference 2019 Tokyo

conf.libreoffice.jp

の基調講演2本の字幕を聞き取りなおして日本語訳もつけたので、 せっかくだからもっといろんな人に見てほしいということで宣伝エントリーを書くことにしました。

言わずもがなですがわたくしの個人ブログに書いてることからお分かりの通り、 ここに書いてあることはLibreOffice日本語チーム、あるいはTDFをいかなる意味でも代表した発言ではござりませぬ。 あくまでもLibreOfficeというプロジェクト、コミュニティに好感を持つ一個人の意見としてお読みくださいませ。

さておき。動画については字幕ONにして、言語を日本語にしてご覧くださいね。

Mark Hung: LibreOffice CJK Bugs, Fixes, and Stories.

www.youtube.com

Mark Hung氏は台湾のLibreOffice開発者です。 主にLibreOffice Writerにて、を日本語で利用するには欠かせない、 アジア言語(いわゆるCJK; Chinese, Japanese, Korean)ならではの組版規則、ルビ、縦書き、BMP外のUnicode文字の扱いなど、さまざまな不具合を修正してきました。 最近ではWriterだけでなく、Impressのアニメーションの改善などにも取り組んでいます。

この講演では、なぜ彼がLibreOfficeに取り組むことになったか、 そしてどういう問題に取り組んできたかを、ストーリー仕立てで話してくれました。

Markのすごみというかは、自分の解ける範囲の問題を着実に解いて、それを意識して広げているってことです。

例えばルビの不具合、彼が直してくれたというときには、そうかー台湾でもルビ使うのかーって素朴に思ってたんですけど、 そうじゃなくて、自分が使ってないけれども領域が近い(CJKな問題)、 直せそうな問題を選んで取り組んだということをこの講演で言ってて、 なんというかそういう姿勢がすごいですよね。

LibreOfficeが持つCJKなさまざまな機能について振り返るという意味でも面白いですし、 それから、彼のLibreOfficeのストーリーのきっかけとなる、 Apache OpenOfficeで数週間放っておかれた不具合がLibOでは翌日レビューされて、 それが理由で組織がLibOを採用した……なんて話も面白いです。

あんまり弁が立つほうじゃないので、TED的なうまさはないですし地味に聞こえるかもしれないですが、 私としては、淡々とした口調であるからこそ、 なおかつ自分の活動を声高に主張しないからこその、 強さがあるなあと思いました。

彼の活動を日本に紹介したい、だから日本で講演してほしい。 それはずっと思ってきたことだったので、 とっつきの派手さがないから動画見られていない、 SNSとかでもあまり言及がない、ということなら、 それはすごいもったいないと思うのですよねー。

ので、とにかく見てほしいです。OSSへの貢献のありかたという意味でも興味深いです!

Italo Vignoli: LibreOffice, the many different faces of a global community

youtu.be

  • タイトル邦訳:LibreOffice、グローバルコミュニティの多様な側面
  • 発表資料(PDF): 英語 日本語

Italo Vignoli氏は、LibreOfficeを法的・財務的に支える非営利組織であるThe Document Foundation(以下TDF)の創立メンバーで、 マーケティング・広報担当コンサルタントとしてTDFと契約しています*1。 TDFが行っているLibreOffice認定制度を行う認定委員会の共同委員長でもあります。

LibreOfficeプロジェクト、プロダクトの説明もしていますが、それよりも、 LibreOfficeを取り巻く世界と、そこにおいてLibreOffice/TDFは何を目指して何をしてきたかという話が、 とても興味深いです。

ソフトウェアライセンスの輸出入の多寡で見る世界地図というところは実に衝撃的で、 LibreOfficeを使ってなくても、日本においてソフトウェアにかかわっている人であれば、 この話を聞くだけのためにぜひ見てほしいです。

またLibreOfficeの前身プロジェクトであるOpenOffice.orgとSun、Oracleの関係、 OpenOffice.orgが商標を譲渡したApache OpenOfficeIBMの関係なんかも、 改めて聞くと面白いんじゃないかと。

まあItaloという人はとにかく弁が立つ人で(そういう意味ではオープニング基調講演のMarkとは対照的)、 若干あおりが入ってるところもありますが、 笑いが絶えない、funかつinterestingな講演でした。

Lothar Becker: Certified as a LibreOffice professional - a win/win/win situation for the community

youtu.be

※Italoの講演の続きとなります。

  • タイトル邦訳:LibreOffice 専門家として認定をうけること - コミュニティにとってWin / Win / Win な状況
  • 発表資料(PDF): 英語 日本語

Lothar Becker氏は、Italoと同じくTDFのLibreOffice認定委員会の共同委員長です。 OpenOffice.orgの時代から、ドイツでもっとも古い移行案件を実施し、またOpenOffice.orgの認定制度を立ち上げるなどの活動をしてきたそうです。 なお、この当時は違いますが、今はTDFの議長を勤めています。

で、この講演は、彼の実績から、LibreOfficeのビジネスとエコシステムとコミュニティ、 そして認定制度についてのものでした。

ええと、正直に申し上げます。わたくし、 Lotharの話、LibreOfficeのグローバルなカンファレンス(LibreOffice Conference、通常LibOCon)で聞いて、 いまいちピンとこなかったんですよね。 じゃっかん抽象論っぽく聞こえて。

というのは、やっぱりあれじゃないですか、 LibreOfficeへの移行を(その動機はさておき)検討した場合、 「いやそんなことできませんよ」となる理由の一つは、 専門家によるサポートが受けられないことだと思うんですよね。 で、なぜサポートできる専門家がいないかというと、 平たく言うとそれでご飯が食べられないからです。市場がないか小さいから。 これってまさに鶏と卵のジレンマですよね。 そこに対するよい答えが、ないように思ってたのです。

でも、今回書き起こしのために時間かけて聞いたら、 自分で自分に「日本市場には適用できない」って言い訳しちゃってたのかもしれないです。

うーん今のところ考えまとまってないのでうまいこと言えないですけど、 まあ自分としてもうちょっとできることあるんじゃないかな、 人のせいにしてないで、そういうことやらないとなーと思える講演ではありました。

また、LibreOfficeの認定制度についてですが、 オフィスソフトの認定制度というとMSさんのMOSとかそういうのがぱっと浮かびますが、 そういうものとは少し違うんですよね。 その点、ちゃんと説明があったのもよかったと感じました。

……ということで三つの基調講演を紹介しました。

それぞれ、少しずつベクトルが違って面白い講演だったと思います。

面白いな、と思ってくださったら、ぜひ高評価、よろしければチャンネル登録もお願いします*2

*1:人呼んでTDFのゴッドファーザー

*2:YouTuberか!

続きを読む

短期集中連載? LibreOfficeをWindowsで開発してみよう:その③ Visual Studioで開発できるようにする

今回も夜までの更新間に合わなくて翌日朝更新。だって試行錯誤のためにフルビルドやり直しになっちゃったんだもん……。

GWの間にLibO開発できる環境をWindowsで作ろうの連載3回目。環境作るだけじゃなくてできればバグつぶしてコミットするところまで行きたい。

過去記事:第1回 第2回

本日は、LibreOfficeはちゃんとIDE連携があるので、そいつを使ってVisual Studio 2019 Communityで開発できるようにしてみましょう。

先に結論:

  • ./autogen.sh 実行時に --enable-debug 忘れずに。
  • makeに vs2019-ide-integration ってターゲットがちゃんとあるのでそれを使おう。

VS2019向けソリューションの作成

LibreOfficeの開発環境の各種IDE連携については、TDFのWikiにちゃんと説明があります。

wiki.documentfoundation.org

で、Visual Studioの説明を見てみますと、どれどれ……。

For Visual Studio 2017:

make vs2017-ide-integration

For Visual Studio 2015:

make vs2015-ide-integration

あれ? VS2019の説明がない。

まあ、とりあえずやってみましょう。

make vs2019-ide-integration

お、通った! これはドキュメントが更新されてないってことですね*1

見ると、ちゃんとVSで読めるソリューションファイルできてる。素晴らしい。ではあとはVS 2019で読み込めばいいのかな?

って、Wikiを見ると、

Note:

You need to build with --enable-debug in order to generate the Visual Studio IDE integration.

ってあるけど……なくても通っちゃったから別にいいのかなー。

VS2019で読み込んでみる

ということで、生成されたソリューションを読み込んでみました……えいっ。

……いけました!

デバッグ実行を試してみたら、ちゃんと自前ビルドしたLibreOfficeも起動します。おーーー。 ただ、起動までが猛烈に遅いんですけどこれは仕方ないのかなあ……。

しかしデバッグができない……。

では、ためしに適当なところにブレークポイント張って、デバッグ実行できるか試してみましょう。

というのはもちろん、さっきのドキュメントの注意書き「--enable-debug しないとだめだよ」が気になってるからですが。

結果をいうとだめでした。 ロジック上はまず通るだろうと思うところにブレークポイント張っててもすこっと抜けちゃう。 ブレークポイントにマウスカーソル当ててみると「シンボル読みこめないからこのブレークポイント無効だよ」みたいなことが書いてある(細かな文言メモってなかったです、すみません)。

あーそうなんだー、やっぱ --enable-debug ないとだめかー。

ということで、まずはVSを閉じてから、

./autogen.sh \
  --with-lang=ALL \
  --enable-64-bit \
  --with-jdk-home=/cygdrive/c/Program\ Files/AdoptOpenJDK/jdk-8.0.252.09-hotspot/ \
  --enable-debug

としといてから、念のため make clean して、

make && make vs2019-ide-integration

して一晩放置しました。

再びチャレンジ……うまくいった、か?

さて一晩経って処理終わってたので、再びVS開いてソリューションを開きなおし、F5キー叩いてデバッグ実行……ん?!

なんか関係ないところで例外吐いてブレークするんですけど……?(OpenCLがどうとかこうとか)

が、しかし、例外吐いてブレークするということは、デバッグは正常に動いてるということになります。

なので、「一回デバッグなしで起動しておいて、起動後デバッグアタッチする」という方法でやってみたら……。

f:id:naruoga:20200504100733p:plain
デバッグブレークできた

おお、ちゃんとブレークしますね。

ということで、Visual Studio 2019で無事デバッグできるようになった。よかったよかった。

なお、さっき書いた「なんか関係ないところで例外吐いてブレークする」は、一度デバッグ実行できるようにあったら再発しなくなりました……なんぞこれ。 初回起動時にしか通らないロジックとかなのかなあ。 まあ、支障はないので、とりあえず放置することにします(弱い)。

難点

とにかくデバッグ実行の起動がすごく遅いです。

LibOのソースの構成は、内部でたくさんのサブコンポーネントがあるわけですけど(参照: Development/Code Overview - The Document Foundation Wiki)、 こいつらが全部DLLとなる関係で、実行のたびに各DLLのビルドプロセスが走るみたいで、 まあその数が50個ぐらいあるわけですから、ソースに変更がない(ビルド不要)という判定をするだけでもだいぶ待たされます。

これ、なんとかならんのかなあ……。そこらへんはおいおい調査ですかね。

できれば、今日は具体的にソースを読み解いて問題を解くところまでやりたいですね。頑張りましょう。

*1:Wikiだから書いちゃえばよさそうだけど、開発素人なので勇気が出ないです(苦笑)。

短期集中連載? LibreOfficeをWindowsで開発してみよう:その② ビルド通りました、小ネタ紹介

いきなり集中連載1日落としてるじゃねーかってすみません。だって、ビルド通すのに苦戦してたんですもの……。

そんなわけでGWの間にLibO開発できる環境をWindowsで作ろうの連載2回目。

過去記事:第1回

今回は前回にも増して行き当たりばったりなので、最適な答え出してる自信ないです……。

ビルドしてみよう!

前回で autogen.sh を通すところまではできているので、あとは同じディレクトリで:

make

するだけ……なんですが、2点ほどハマりました。

submodule "translations" の取得に失敗してビルドがこけたあと回復不能

これがねー、けっこう解決に時間要しました。

正直、LibOのソースコードが置いてあるgerritですけど、 こいつがどうも能力いっぱいいっぱいなのか、それとも我々極東から離れて遠いヨーロッパにサーバーがあるせいなのか、 大きなリポジトリのcloneがタイムアウトでコケることがあるんですよね*1

で、LibreOffice coreのリポジトリは三つのsubmodule*2 があります。 そのうちの一つ、ウェブ翻訳システムWeblate の成果を取り込む translations というサブモジュールがありまして、 こいつはcloneしたあとのファイル数が23000ぐらいある、まあまあでかいリポジトリです。

なので、5/1の記事を書いた後、寝る前に make 叩いてビルドして、朝起きて結果見たら…… translations を取ってこれなくてビルド落ちてたんですね。

これは、まー、あー、しょうがないか……で、もう一度 make 叩いたのですが。 何度か試してるうちに、なぜか translations が正常にとってこれなくて空っぽなままなのにビルドが進むようになってしまい、 当然 "translations" 以下のファイルがないので途中で落ちてしまう……えー。なんでー。

ここもいろいろ試行錯誤したんですけど、結論からいうと以下のコマンド叩いたら復活できました。

git submodule deinit translations
git submodule init translations

要はいちどsubmoduleと、リモートリポジトリの紐づけ外してもう一度付けなおすみたいな感じですね。

これでもう一度 make 叩いたら、無事、translations の取得はできて*3、ビルド流れ始めました。やった!

Visual Studio 2019のコマンドラインツール( cl.exe とか)のメッセージを英語にする

で、ビルドの途中経過見ると、

□□□□: □C□□□N□□□[□h □t□@□C□□:        C:/cygwin/home/naruhiko/lode/dev/core/workdir/UnoApiHeadersTarget/offapi/normal\com/sun/star/chart2/data/XDataSequence.hdl
□□□□: □C□□□N□□□[□h □t□@□C□□:         C:/cygwin/home/naruhiko/lode/dev/core/workdir/UnoApiHeadersTarget/offapi/normal\com/sun/star/chart2/data/LabelOrigin.hdl

こんな感じになっちゃってます。 あーなるほど、VS2019同梱のコンパイラ cl.exe とかが日本語吐くからだな。

じゃあ、英語にしましょう。 最初この↓ 記事を参考にしたんですが(VS 2017の記事だけど手順は一緒かなって)、

usagi.hatenablog.jp

うまくいかなかったので*4、 もうあたま来て、日本語の言語パック消して英語のに入れ替えちゃうことにしました。

言語パックの追加削除はVisual Studio Installerで行います。前回の記事だと

Visual Studio 2019起動して、「コードなしで続行」選んで、ツール > ツールと機能の取得 を開きまして。

という動線を紹介しましたが、素直にVisual Studio Installerを起動>「Visual Studio 2019 Community」を選ぶ、でもいいです。

で、「言語パック」タブにて「英語」をチェックして、代わりに「日本語」のチェックを外して「変更」。

f:id:naruoga:20200503075132p:plain
日本語を消して英語だけにしちゃう

試してみますと、

>"c:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\bin\Hostx64\x64\cl.exe" /?
Microsoft (R) C/C++ Optimizing Compiler Version 19.25.28614 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

                         C/C++ COMPILER OPTIONS


                              -OPTIMIZATION-

/O1 maximum optimizations (favor space) /O2 maximum optimizations (favor speed)
/Ob<n> inline expansion (default n=0)   /Od disable optimizations (default)
/Og enable global optimization          /Oi[-] enable intrinsic functions
/Os favor code space                    /Ot favor code speed
/Ox optimizations (favor speed)
/favor:<blend|AMD64|INTEL64|ATOM> select processor to optimize for, one of:
    blend - a combination of optimizations for several different x64 processors
    AMD64 - 64-bit AMD processors
    INTEL64 - Intel(R)64 architecture processors

わーい。英語になった。

巻き添えとして? VS2019のGUIも英語になっちゃいますが、まあ、いいですよね*5

あと、今思ったのですが、一度ビルド通した後はVS2019統合で開発できる*6 から、この手順要らんかった気がするな……。

動いた!

まあそんなわけで待つこと……どれぐらいだろ? 1時間よりは長くて8時間よりかは短い*7 感じかなー。

前にビルドしてたのはThinkpad X220 (Ubuntu)で4時間ぐらいだったかな、マシン早くなったのでもうちょっと早いかと思ってましたがHDDなのがいけないのか。

ともかく私家版ビルド、無事動きました! ビルドしたcygwinターミナルにて instdir/program/soffice & で起動できます。

f:id:naruoga:20200503080026p:plain
ビルドしたLibreOfficeのAbout画面

このリリースはnaruhikoが提供しました。

が誇らしい? ですね。

まーよかったよかった。ではまた次回の連載記事をお待ちください!

*1:前回紹介したlodeの導入手順も、coreのコードcloneしてくるのでその可能性はありました。私は問題なくできましたが。

*2:submoduleがわからない人はgit submoduleでググりましょう。私submoduleの使い方自信なくて毎度ググってる……。

*3:ものすごーーーーーく時間かかりましたけど。

*4:VS2019の機能で開発コンソール開くと英語になるのでよしよしって思ったら、 コマンドプロンプトから実行すると日本語のまま。今考えると環境変数とか見てるのかもしれない。

*5:というか、最初からVS2019英語で導入すればよかったのでは……?

*6:……たぶん。さりげなく次回予告ですが今日はこれを試す予定。

*7:幅あってすみません、別のパソコンで作業してほっといてたら、いつの間にか終わってたので。

短期集中連載? LibreOfficeをWindowsで開発してみよう:その① ビルド環境の構築

GWでヒマ? なのでLibreOfficeの開発というかバグ直しみたいなのに挑戦してみたいですね。 先日買ったThinkpad T470は結局しばらくWindowsで運用することにしたので、じゃあWindowsで開発に挑戦してみましょうと。

ということで短期集中連載開始。途中で力尽きたらごめんなさい。

有識者が皆様にノウハウをご教示するみたいなものではなく、むしろ私の作業メモ。なので嘘とか間違いもあるかも……。

さてと。初回のこれはビルド環境の構築。 といってまだビルドはできてません。 ./autogen.sh が通ることを確認したところまで。

Windowsの環境作ったの記憶にないほど昔か、もしかして初めてなのですが、今はlodeあるんで楽ですね。

wiki.documentfoundation.org

でもlodeだけでは環境できないので、以下も参照して必要なものも入れないといけません。

wiki.documentfoundation.org

Visual Studio 2019 Communityのインストール

最初はBuilding LibreOffice on Windows with Cygwin and MSVC: Tips and Tricksの方を参照しつつ。

Visual Studioをインストールします。私はchocolateyでさくっと。 管理者モードで実行したコマンドプロンプトにて:

C:\WINDOWS\system32>choco search visualstudio2019
Chocolatey v0.10.15
apincoree-vsix 3.9 [Approved]
...
visualstudio2019-workload-nativedesktop 1.0.0 [Approved]
...
visualstudio2019teamexplorer 16.5.4.0 [Approved]
visualstudio2019professional 16.5.4.0 [Approved]
visualstudio2019testagent 16.5.4.0 [Approved]
visualstudio2019testcontroller 16.5.4.0 [Approved]
visualstudio2019buildtools 16.5.4.0 [Approved]
visualstudio2019community 16.5.4.0 [Approved]
visualstudio2019enterprise 16.5.4.0 [Approved]
38 packages found.

ドキュメントによれば「Desktop development with C++」ワークロードも導入せよとのことですので、 たぶん「visualstudio2019-workload-nativedesktop」を一緒に入れることもできると思いますが、 私はいったん本体だけ入れて各種コンポーネントは後入れすることにしました*1

C:\WINDOWS\system32>choco instal -y visualstudio2019community 

次はコンポーネントのインストール。ドキュメントによれば以下のものが必要だそうです。

  • MSVC v142 - VS 2019 C++ x64/x86 build tools (v14.2x)
  • C++ core features
  • Windows 10 SDK (10.0.xxxxx.x)
  • Windows Universal C Runtime
  • C++ ATL for v142 build tools (x86 & x64)
  • .NET Framework 4.x.x SDK
  • C++ 2019 Redistributable MSMs (only required to build MSI installer; not part of the "Desktop development with C++" workload)
  • C++ Clang Compiler for Windows (9.0.0) (not part of the "Desktop development with C++" workload)

Visual Studio 2019起動して、「コードなしで続行」選んで、ツール > ツールと機能の取得 を開きまして。

  • C++によるデスクトップ開発」を選んで、標準でチェックされてるものに加えて「Windows C++ Clangツール(9.0.0 - x64/x86)」もチェック。

ついで「個別のコンポーネント」で、「.NET Framework 4.8 SDK」および「C++ 2019 再頒布可能パッケージ MSM*2」の二つを選んで。

f:id:naruoga:20200501131134p:plain
ワークロード・コンポーネントの導入

これで「ダウンロードしながら変更する」して「変更」を押下するとよい……はず。

JDKのインストール

お次はJDKを入れます。ドキュメントによれば:

Java Development Kit (JDK) Version 8 or later. Make sure to get a 32-bit SDK if you are building for 32-bit Windows, and a 64-bit SDK if you are building for 64-bit Windows (with --enable-64-bit). Grab it from http://www.oracle.com/technetwork/java/javase/downloads/index.html.

とあります。 JDK8以降ならいいみたいなので13EAとか入れるのが男なのかもしれないですが、 弱気なのでJDK8です……へたれ*3。 上を見るとOracleJDKを使うように読めますが少なくともAdoptOpenJDKはいける……はず*4

あとぼーっと読んでたら 「Make sure to get a 32-bit SDK」って部分が目に飛び込んで、えってなったんですが(私だけ?)、 後ろに「if you are building for 32-bit Windows」ってあるので、普通に64bitで大丈夫です。

ということでこれもChcocolateyです。

C:\WINDOWS\system32>choco install -y adoptopenjdk8

インストールできたら確認しましょう。別途コマンドプロンプトを開けて、 java コマンドと javac コマンドの両方が使えればOKと。

C:\Users\naruhiko>java -version
openjdk version "1.8.0_252"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_252-b09)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.252-b09, mixed mode)

C:\Users\naruhiko>javac -version
javac 1.8.0_252

ポリシーの確認

ここからは再びlodeのドキュメントを参照しつつ。

最初にlodeの導入手順ではPowerShellスクリプトを実行しないといけないので、ポリシーで許可されてるか確認して、必要なら許可してあげます。

PowerShellにて:

PS C:\Users\naruhiko> Get-ExecutionPolicy
RemoteSigned

で、ドキュメントを見るとUnrestrictedにしなさいと書いてありますが、たぶんRemoteSignedでも問題ない……というか、私はうまくいったのでそのまま。

cygwinの導入

そして、

https://git.launchpad.net/~documentfoundation/df-libreoffice/+git/lode/plain/bin/install_cygwin.ps1

を取ってきて c:\cyginstall において、PowerShellを管理者モードで起動して実行してあげると。するとcygwinが必要なパッケージともどもインストールされます。

おまけ:CygwinWindows Terminalで使えるように

これで使えるようになったんですがminttyが気に入らんので(?)、 WSLでも使ってるWindows Terminalを使えるようにしました。

手順はQiitaの記事:

qiita.com

のとおりですけど、chere 入れるための setup-x86_64.exec:\cyginstall\packages 以下にあること、cygwin bashのパスは c:\cygwin\bin だということだけ。快適。

lodeの導入

次もドキュメントの通りにやるだけ。cygwin開きまして、

git clone https://gerrit.libreoffice.org/lode
cd lode
./setup --help

これでヘルプが出て、

./setup --prereq

これで「Done.」と出れば依存関係チェック含めてオッケーと。

そしたらお次は

./setup

しまして*5、 これも正常に終わったら、ドキュメント通り ~/.bash_profie に以下の内容を書いて source するかcygwin bash抜けて入りなおします。

export LODE_HOME=/home/<user>/lode
PATH="${LODE_HOME}/opt/bin:${PATH}"

「環境」の作成

lodeには「環境(environment)」という考え方がありまして、 まあ要は開発してるとmasterブランチをビルドする場所と例えば6.4系をビルドする場所を両方維持しておきたいなーとか思うわけですけどそういうのを切り替えるってことですかね。

ドキュメントにしたがって dev/core という環境を作りましょう。

./setup --dev --force

するとLibreOfficeソースコード・レビュー管理システムGerritから ./dev/core にLibreOfficeのコードが一式cloneされてビルドできる環境が整うはず。 Gerritちょっと遅いのでclone結構遅いので、ご飯食べに行くなりお風呂入るなりする前にやっとくといいでしょう。

ウィルススキャンソフトの例外フォルダの設定

で、ウィルススキャンソフトの例外設定しないとパフォーマンスつらいので設定します。

と、あたかも自分はちゃんとやったかのように書いてますが、私自身は後述の autogen.sh のときに怒られて*6、あっと思ってやりました。 具体的な手順は環境によって異なるでしょうから省略。 C:\cygwin\home\<username>\lode\dev 以下を例外フォルダに入れとくとよいと思います。

./autogen.sh の実行

ここまで来たら ./autogen.sh が通れば、まあ必要なものはそろってるんじゃないかといえるので。結果的に私のオプションこんな感じで通りました。

 ./autogen.sh --with-lang=ALL --enable-64-bit --with-jdk-home=/cygdrive/c/Program\ Files/AdoptOpenJDK/jdk-8.0.252.09-hotspot/
  • --with-lang=ALL は全言語有効にしてビルド。まあenとjaだけでもいいんですけどね。
  • --enable-64-bit は前述の「64ビットビルドするならJDKは64ビットね」に書いてあったやつ
  • --with-jdk-home AdoptOpenJDKのインストールした場所

はーやれやれ。

ということで次の記事はデバッグして動いたやつを起動する、ぐらいかなー。 それは(ビルド待ってる時間はかかるけど)手間としては一瞬なはず。

*1:……というか、オンラインイベント参加しつつ作業してたらワークロードなどなど必要だよって記述を見落としてました。間抜け。

*2:こっちはインストーラ開発するんでなければ不要らしいですが、まあいちおう。

*3:8から上のバージョンで何が変わったのか追っかけてないんですよねー。モジュールとかvarとかGraalVMとか?名前しかしらない。

*4:LibOは内部でJDKの名称見てるところがあるので、OpenJDKの全ディストリビューションがOKだとはいえなかったはず。

*5:ここら辺ビール飲みながら作業してたのでちゃんと覚えてない……。

*6:autogen.sh のなかでeicarファイルというダミーウィルスを突っ込んで検知するっぽい、かしこい。

OpenDocument Format(ODF)の標準化について雑な補足説明

https://blog.documentfoundation.org/wp-content/uploads/2018/09/odf-community.jpg

この記事は、先日TDF Blogで公開された記事「ODF 1.3 approved as OASIS Committee Specification」(日本語訳「ODF 1.3、OASIS委員会の標準として承認」)の補足説明的ななにかです。

ほんとうは、標準化とかそういう「きちんとした」世界についてなにかものを申すには、きちんと下調べをして裏付け取ってなるべく正確なものいいをすべきだと思うのですが、正直、「ちゃんとする」には現状気力体力が足りないため、他人様の受け売りその他で雑に述べます。なので眉につばをたっぷりつけてお読みくださいませ……。

じゃあなんでそういう雑な記事を書くかというと、ちょっとウェットな物言いをすると、標準化で提供しようとしている価値に対して色んな人が色んなことをしてくれているんだなあという私個人の感謝の気持ちをみなさんと共有できたらなあという動機です。

OpenDocument Formatとは

LibreOffice*1 のネイティブドキュメントフォーマットで、いわゆるオフィスアプリケーション向け文書のフォーマットです。通称ODF。ファイル名として「*.odt」とか「*.ods」とかなってるやつです。

jp.opendocumentformat.org

中身は概ねZIP圧縮されたXML(と、添付されたコンテンツ、たとえばビットマップなど)の塊です。

ODFの特徴は前掲サイトなどを見ていただくとして、一言で言ってしまえば、

真に相互運用することを考えたフォーマットであること

で、もう少し細かくいえば:

  • 人類でも読める程度の仕様
  • 人類にわかりやすく機械加工も容易な構造
  • 豊富な操作ライブラリ(参考サイト

あたりでしょうか。

ここで本来はODFについての説明をひとくさり書くべきで、というか実際ちょっと書きかけたのですが、わたしの理解が覚束なくて書き上げるのにそうとう時間がかかりそうなのと、あと長くなるので今回は割愛して裏付けのない雑な説明。

ODFを構成するXMLですが、見た目はこんな感じのやつですね。

<?xml version="1.0" encoding="UTF-8"?>
  〜略〜
  xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
  〜略〜
  office:version="1.2">
<office:scripts/>
〜略〜
<office:body>
    〜略〜
    <office:text>
        </text:sequence-decls>
        <text:p text:style-name="P1">
            <text:span text:style-name="T4">井神陽吉は風呂が好きだった。</text:span>
        </text:p>
        <text:p text:style-name="P1">
            <text:span text:style-name="T4">殊に、余り客の立て混こんでいない昼湯の、あの長閑な雰囲気は、彼の様に所在のない人間が、贅沢な眠から醒めたのちの体の惰気を、そのまま運んでゆくのに最も適した場所であった。</text:span>
    </office:text>
</office:body>
</office:document-content>

(テキストは海野十三「電気風呂の怪死事件」より。青空文庫リンク

XMLはHTMLとかと同じでタグで文書の構造を定義します。例えば <text:p> は、テキストであってさらに段落(ParagraphのP)であるということを意味するタグです。このような「どんなタグがあって、それがどんな意味を持つのか」が、ODFのようなXML文書の仕様を定義するってことです。

「どんなタグがあって」ってのがいわゆるスキーマ定義。XMLスキーマ定義をする方法にはいくつかあって、ODFの場合はRELAX NGというスキーマ定義言語を用いてます。

で、スキーマ定義はタグの定義だけじゃなくて、例えば同じ <text:p> を違う意味で使うXML文書と混在したりしたら困る。で、「ODFでは*2<text:p> タグはこういうふうに意味を決めるからね、というのを定義するのが名前空間というやつで、 xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" とか書いてるのがそれですよと。

もちろんスキーマ定義、名前空間だけじゃダメで、それぞれのタグの持つ意味も定義しないといけない。例えばODF 1.3の <text:p> タグの定義は:

The <text:p> element represents a paragraph, which is the basic unit of text in an OpenDocument file.

つまり段落を表す要素ですよと書いてあると。

ともかく、文書フォーマットとしてはスキーマと意味がそろってればよく、それにしたがってアプリケーションを実装すれば、異なるアプリケーションでも文書交換が可能で、相互運用可能になる……と、いうわけです*3

相互運用うんぬんについて補足すると、例えばODFにはODF Validator ってサービスがあって、これは適当なファイルを放り込むと、ODFのスキーマ定義ファイルに照らし合わせてODFの定義に従ってるかを判定してくれるサービスです。このバックにいるのはODF Toolkitってライブラリで、こいつは単なるODFの操作ライブラリではないさらに先を目指して開発されてる……とか。こういう取り組みがあることが、ODFが単なる「LibreOfficeのファイル形式をなりゆきで文書化しただけ」というもの以上を目指していることを示してると思います。

ODFが「国際標準」であるということ

大事なことはODFはLibreOffice専用のフォーマットでなければLibreOfficeコミュニティあるいはその支援を行う非営利組織The Document Foundation(TDF)のものではなくて、その他のアプリケーションも自由に使えるってことです。現にMicrosoft OfficeGoogleドキュメントもODFは扱えますし。

それを保証してるのが、ODFが「国際標準」であるということ。つまり、LibreOffice/TDFが手前勝手に仕様をどんどん変えていくのではなくて、オープンな場所で「標準」として仕様を管理して、それを公開して、色んな人が使えるようにするということです。

例えばHTMLがどんなブラウザでも正しく表示できるように、PNGがどんなビューアでも表示できるように。

でもそれって、LibreOfficeの進化を妨げるようなことはない?

でも、あれですよね、新しい機能を追加すると、当然その機能によって追加されたなにがしかをファイルに保存したくなるわけですよね。それがこれまでにあったXMLタグで表現できない場合は、タグをあらたに追加しないといけない。しかし、いちいち標準化団体にお伺いを立てないと新規にタグを追加できない……そんなことしてたらソフトウェアは進化できない。ですよね。

なので、ODFにはOpenDocument Extended Documentというやつがあって、要はODFの仕様に準じて、さらに独自のタグを追加できるよということ……だと私は理解してます。LibreOfficeの場合は loext というprefixがついたタグは独自拡張です。どんな独自拡張があるかはWikiに記録されてます。

で、当然ですが、「私たちはこういうふうに思ってこういう独自タグを定義したけど、それをODFの標準に入れてよ」という働きかけをするわけですね。ODF 1.3は、そういう取組みであらたにタグが定義されましたと。

なので、ODF1.2には存在しなくて、でもLibreOfficeには存在して、ODF 1.3で追加されたものは、ODF 1.3に対応したLibreOffice、つまりLibreOffice 6.4のさらに次のリリースでは、独自タグからODF 1.3で定義されたものに移行されるはずです。

こうやって、アプリケーションと標準が共に進化をしていくよというのが、ODFが「正しく」標準であるということ、だと思います。

具体的にODF 1.3って何が変わったの? という人は、「Open Document Format for Office Applications (OpenDocument) Version 1.3. Part 3: OpenDocument Schema」の「Appendix G Changes From ODF 1.2 (Non Normative) 」を参照してくだされ。

ODFとOASIS、ISO、JIS

ODFの仕様は、OASISという標準化団体で策定されています。

www.oasis-open.org

前述のように標準化とかについては私ぜんぜん詳しくないのでアレなんですが、もともとOASISSGML関係の標準化とかをやってたSGML-Openという団体が元で、SGMLからXMLを含んだ形で活動を広げるためにOASISって名前になったんだそうな。Wikipediaより。たぶん富士通さんのワープロとは関係がないです。ODF以外だとCMISとかDocBookの標準化が有名かしら。

で、OASISに限らないですが、標準化団体というのはそれぞれの標準に対して技術委員会(Technical Committee)というのがあって、個別の標準はそこで議論され策定されていくということになってるらしい。で、ODFについてのTCが Open Document Format for Office Applications (OpenDocument) TCです。で、そこで「こいつは標準文書とするよ」というプロセスに従って定められた標準が「委員会標準」という……らしい。前述の記事の

OASISは、OpenDocument TC(技術委員会)からのOpen Document Format for Applications (OpenDocument) v1.3がOASIS委員会標準(OASIS Committee Specification)として承認された

っていうのはそういうことです。

前述のようにLibreOfficeがODFに対して独自に拡張した部分に対し、必要と思われるものはOASISに提案して仕様に取り込んでもらう努力をしております。その取り組みは前述のODF拡張のWikiページでも見られますし、また去年のLibreOffice Conferenceの資料なんかも参考になるかもしれないです。

また国際標準というとぱっと頭に浮かぶのはISOかと思いますが、

www.iso.org

ISOも必ずしも直接規格を議論するわけじゃなくて、ODFの場合だとOASISの委員会標準をISOの議論に乗せて、それを標準として策定する……ってプロセスを踏むっぽいです*4。ISOの場合は、TCの下にSub Committee(副委員会?)、さらにその下にワーキンググループがあって、ODFの場合はISO/IEC JTC 1/SC 34/WG 6ってワーキンググループで作業されてるらしい。ISO/IEC JTC 1が情報技術のTC、SC 34がドキュメント記述および処理言語(Document description and processing language)ですね。

でまあ、ODFはISO標準でもありますよ……と言われます。ISO/IEC 26300というのが規格番号で、現在の最新は ISO/IEC 26300-1:2015、ISO/IEC 26300-2:2015、ISO/IEC 26300-3:2015の三つで、これがODF v1.2という規格に対応してます。

いまのところ私が聞いてるところでは、今回ODF v1.3は今回の委員会標準化を経てISOのWGに議論が移され、2020年中の改定(ISO/IEC 26300-n:2020?)となる……んだと、思います。

なお、国内で規格といえばJISでございますが、残念ながらJISのODFについての規格JISX4401ってODFのバージョンでいえばv1.1の翻訳なんですよねえ……。なのでこれが早晩改定されるのは期待薄かも。

まとめ

ということでODFは真に相互運用可能であることを目指したオフィスアプリケーション向け文書フォーマットの国際標準なのです。ODFを選ぶことはLibreOfficeも含むあらゆるアプリケーションにロックインされないという意思決定なのです。大げさにいえば。

そんなわけでODF 1.3、OASIS委員会標準化おめでとうございます!

ISOの更新に向けてもがんばってください! Love! ODF!

*1:もちろん、前身プロジェクトであるOpenOffice.org、およびその商標を受け継いだApache OpenOfficeも。

*2:厳密には「ODFのこの部分では」ですかね。

*3:もちろん、スキーマ定義と各タグの意味だけでは表現しきれない、アプリケーション仕様というのも、もちろんあります。

*4:すべてのWGで同様かどうかは、まったく存じません。

続きを読む