ruby-2.1.2のlibffi-3.1対応
チケットが来てたので対応しました。
内容についてはrubyのissie#9897にあるとおりです。
いちお簡単に説明すると、ビルド時にマクロとしてRUBY_LIBFFI_MODVERSIONという値を定義しているのですが、従来の"3.0.13"のような数字3つのバージョンから"3.1"という数字2の形式に変わったため、その値に入れるバージョンの加工に失敗してfiddleがコンパイルされないという状況になっていました。
trunkやruby_2_1ブランチでは修正済みだったので、その変更を適用しました。ruby-2.0ではRUBY_LIBFFI_MODVERSIONを使っていないためこの問題はありません。
また、別件で新しいXcodeでdlモジュールがインストールされないという問題があったので合わせて対応しています。
port:ruby21でfiddleが使えないなどの状況が起きた場合は、port upgrade ruby21で解消すると思います。
RubyCocoa 1.2.0 リリース!
しました。ついにRuby 2.0以降に対応しました!(1.9は対応しません)
ちょっとパッケージング失敗したので、日本時間で今日の14:30以前にダウンロードした人は取り直したほうがよいかもです。
変更点をNEWS.jaから抜き出し。ruby-2.0対応したのが中心で、他は特にありません。
== 1.1.0から1.2.0の変更点: 2014-07-27 === 改良 * ruby-2.0に対応しました。おおむねruby-1.8と同様に動作します。 * RubyCocoaのインストーラはruby-1.8用と2.0用で別々のファイルとして リリースされます。RubyCocoaアプリケーションをOS X 10.9添付のruby-2.0で 動作させてみたいときは、RubyCocoa.frameworkを入れ替えてください。 * 存在しないメソッドが呼び出されたときの例外をNoMethodErrorに変更しました。 (以前はOSX::OCMessageSendExceptionでした。) === 廃止された機能 * CocoaClass#objc_export()は廃止されました。objc_method()を使ってください。 * OSX::NSObject#ocm_responds?()は廃止される予定です。ocm_respond_to?()を使ってください。 * OSX::NSData#dataWithRubyString()およびOSX::NSMutableData#dataWithRubyString()は 廃止される予定です。[NSString dataUsingEncoding:]を使ってください。 === 修正 * Yosemite DP上でのビルドエラーを修正しました。 === RubyCocoaをRuby-2.0上で使う際の注意 * ruby-2.xの文字列はエンコーディングを保持するようになります。詳しくは https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/MigrationIssuesFrom18 や http://magazine.rubyist.net/?0025-Ruby19_m17n をごらんください。 * (frameworkでない)bundleやdylibのObjective-CのクラスをRubyのコードで 拡張したいときは、OSX.ns_importを書くようにしてください。 require 'path/to/your_bundle.bundle' OSX.ns_import :YourClass module OSX class YourClass : # extend class in Ruby code end end
RubyCocoa.frameworkが、ruby-1.8用とruby-2.0用が存在することになるので、Finderに表示するようにしてみた。
今後の予定
このくらいですかねえ。
- Ruby <=> Objective-Cの文字列変換時のエンコーディング変換を指定するインターフェイスつける。
- xibのib_outletやib_actionが認識されない件の対処。
- blocks対応したい。
最後のはまだアタリもつけてないけど、簡単にできるとよいなあ。
RubyCocoa 今週のコミット ..2014-07-26 10.6/10.7での初期化エラーを修正
細かいとこではドキュメント更新したり、コンパイル時の警告つぶしたりしてた。
大きい作業としては、Snow LeopardやLion環境では"trunkでrequire 'osx/cocoa'しただけで落ちる"という致命的な問題があってその対応をしていた。
エラーメッセージはこんなの。
"/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby" -I../e xt/rubycocoa -I../lib testall.rb 2014-07-25 05:48:43.038 ruby[4778:60f] *** NSInvocation: warning: object 0x7 fff708db850 of class 'Object' does not implement methodSignatureForSelector: -- trouble ahead 2014-07-25 05:48:43.041 ruby[4778:60f] *** NSInvocation: warning: object 0x7 fff708db850 of class 'Object' does not implement doesNotRecognizeSelector: - - abort test failed
ようするに(Objective-Cの)Objectクラスを処理しようとしてエラーになってるわけだ。
Objective-Cのクラスの話
前提として説明すると、Objective-CのランタイムにあるすべてのクラスがCocoaのクラスというわけではない。Cocoaでは、NSObjectとNSProxyの2つのルートクラスがあり、ほとんどはNSObjectの派生クラスとしてFoundation等のフレームワークは構成されている。
で、それらとは別系統のクラスもあって、たぶんObjective-C組み込みと思われる"Object"クラスなんてのもある。
// OS XのObjective-Cのクラス階層 + NSObject + NSArray | + NSMutableArray + NSResponder + NSView + NSText | + NSTextView + NSTableView + NSProxy + Object # <= NOT a Cocoa class
ちなみに、今までほとんど表にでてこなかったObjectクラスなんだけど、SwiftのクラスはこのObjectクラスの派生クラスになってるという話もあるみたいね。
話を戻そう。(最近の)RubyCocoaでは、この「Cocoaのクラスかどうか」を
- 自クラスまたはその親のクラスがNSObjectプロトコルに適合しているかどうか
で判定している。実装はこんな感じ。
// framework/src/objc/mdl_osxobjc.m /* * Detects Cocoa Objective-C class or not with protocol "NSObject". * - NSObject => YES * - NSProxy => YES * - Object => NO */ static BOOL class_is_cocoa_class_p(Class klass) { Protocol *proto = objc_getProtocol("NSObject"); Class klass_sup = klass; while (klass_sup) { if (class_conformsToProtocol(klass_sup, proto)) { return YES; } klass_sup = class_getSuperclass(klass_sup); } return NO; }
今回のエラーの話
RubyCocoaでは、できるだけObjective-Cのクラス階層をRuby側でも再現するために、あるクラスがRuby側に現れたとき、そのスーパークラスもRuby側に呼び出すようにしている。今回はその機能でひっかかるとこができてた。
RubyCocoaの初期化時にOSX.ns_import_allでぜんぶのクラスをRuby側に持ってくるようにしているんだけど、そのとき処理対象となるProtocolクラスのスーパークラスがSnow Leopard環境などではObjectになってる。でObjectクラスをRuby側で扱おうとしてもCocoaなクラスじゃないのでRubyCocoaを通した操作ができない。でエラーになるというわけ。
RuntimeBrowserで実装を見てみると、ProtocolクラスのスーパークラスがMavericksではNSObjectに、Snow LeopardではObjectになっていることがわかる。
// OSX 10.9 Mavericks @interface Protocol : NSObject { // OSX 10.6 Snow Leopard @interface Protocol : Object <NSObject>
これを解消するためには、OSX::Protocol.oc_superclassがnilを返す(スーパークラスなし)ようにすればよい。つまり、Objective-Cのメソッド呼び出しの結果がClassで、そのクラスがCocoaのクラスじゃないときにはnilを返すように変更することになる。
関連するコミット。
- Cocoaのクラスかどうかの判定基準をisKindOfClass:でなく、NSObjectプロトコルに適合しているかどうかに変更。10.8以前では+[NSProxy isKindOfClass:]を呼び出すとエラーになるため。(r2618)
- Cocoaのクラスかどうかの判定を関数class_is_cocoa_class_p()に切り出し。(r2620, r2622)
- メソッドの返り値がクラスで非Cocoaのクラスのときnilを返すようにする。(r2626)
これでOS X 10.6 - 10.9の環境でtrunkのテストがぜんぶ通るようになった。
RubyCocoa 今日のコミット 2014-07-21 NSData.dataWithRubyString()をdeprecatedに
いちおRC出したのでそんなにいじるつもりはないので、yardのドキュメントをメンテしたり。
便利メソッドとしてOSX::NSData.dataWithRubyString(str)というメソッドが昔からあるんだけど、使い道があんまりないなーと思った上に、そもそもエンコーディングなしにバイト取るのもどうなんだろ?と思ったのでdeprecatedにした。NSMutableDataのメソッドも同様。
- yardで@deprecatedを指定。NEWSにも書いた。実行時にはwarnする。(r2611)
- テストで使ってるとこを必要な箇所を除きNSString#dataUsingEncoding()に直した。(r2612)
- NSData#lengthのテストに非asciiなデータも足しておいた。(r2613)
たぶん誰も使ってないと思うので、1.2の次の次くらいのリリースで削除します。
RubyCocoa 1.2.0 RC (Ruby-2.0対応版)を公開
RubyCocoa 今週のコミット ..2014-07-20 サンプルアプリの動作確認
sample/以下にあるアプリの一覧をつくって、ひたすら確認して直してた。
- もともとおかしかったぽい
- make系のプロジェクトで-framework AppKitが足りない。
- import
足しておいた。
- ruby-2.0によるもの
- ruby-2.0でSyntax Errorになるものを直した。
他のアプリのプラグインとかは確認するのが大変なのでコンパイルできるとこまでしか確認していないです。
WebVTTファイルを利用して動画に字幕を付ける
小ネタ。自分用のメモです。
WWDCのtranscriptをテキスト化しているasciiwwdcのリポジトリwwdc-session-transcriptsをながめてて、拡張子".vtt"てなんじゃろと思って調べてみたところ、WebVTTという規格のテキストであることがわかった。
テキストはこんな感じで、字幕のテキストの他に表示する時間や表示する形式が書かれている。シンプルな構造だね。
WEBVTT X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000 00:00:13.236 --> 00:00:14.526 A:middle >> My name is Olivier Bonnet. 00:00:14.526 --> 00:00:18.266 A:middle I'm the engineering manager for the CloudKit on the client side.
動画と組み合わせて字幕を表示させるには、html中のtrack要素で書いてやればよい。
<video controls autobuffer autoplay loop id="wwdcvideo" width="100%"> <source src="./2014/408_sd_swift_playgrounds.mov" type="video/quicktime" /> <track kind="captions" src="./2014/408.vtt" type="text/vtt" srclang="en" label="English Subtitles" default /> </video>
ちなみに2014年のWWDCの動画には最初から字幕データが入っているので、こんなことしなくても字幕付く。てゆか二重に表示される。
いやさ、Safariでそのまま見てると最大化しないと字幕のオプションでてこないから、気付かなかったんですよ!
RubyCocoa 今日のコミット 2014-07-14 インストーラ作成スクリプトの調整
10.9 Mervericks用はruby-1.8とruby-2.0の両方がOSに付いてるので、それぞれ用のRubyCocoa.frameworkのインストーラをリリースする予定。なのでそのあたりの調整あれこれ。
- リリースファイルの名前を自由に指定できるように。 (r2587)
- パッケージ作成時の設定ファイルをコマンドラインから渡せるように。 (r2588)
- 10.9+ruby2.0用の設定ファイルを追加。(r2589)
今は自動的に"RubyCocoa-1.1.0-OSX10.9.dmg"などの名前を生成しているけれど、任意の名前も指定できるように。単にRubyのバージョンを足して、
になる予定。
パッケージ作成時の設定ファイルをpackage/config/以下におくようにして、`ruby install.rb package`で該当OSバージョンのファイルを使うんだけど、OSのバージョンが同じなので実行時のコマンドラインオプションで選べるようにした。
% ls -1 package/config/ 10.4 10.5 10.6 10.7 10.8 10.9 10.9-ruby2.0 # <= NEW!
エンコーディングの件はまだちょっと悩み中。現在の案だとどうせ直すことになりそうだし、UTF-8使えれば現在の1.8レベルの利用は問題ないはずなので、次の次のバージョン(1.3?)に送っちゃおうかなあ、、とひよっている。今週末までの進行具合で判断しますです。
port:pecoを0.2.0に更新
しました。
先日MacPorts公式にport:pecoを登録してから気付いたんだけど、peco-0.1.12とMacPortsのportコマンドとの組み合わせで、どうも動作がおかしい。portの出力をpecoに渡すとそのまま固まってしまう(killしないと終了できない)。0.1.11以前は問題なかった。
pecoの変更を追っかけてみると、0.1.11と0.1.12で入力バッファの処理が変更されていて、どうもそのへんじゃないかと思ってレポートしたりして、報告した問題は解消されたんだけど、portだけまだおかしい。これはたぶんportが悪いんだと思う。
仕方ないので、パイプでつながないようにすることにした>"pbcopy; pbpaste"のあたり。
% sudo port selfupdate % sudo port upgrade $(port outdated | pbcopy; pbpaste | peco | cut -f1 -d\ )
これで更新したいのを選ぶとupgradeされる。地味に便利。