Hatena::ブログ(Diary)

きりかノート 2冊め

2016-11-25

[]Mac App Store用のコマンドラインツール mas を登録

コマンドラインでMac App Store経由のインストール、更新などの操作ができる mas (mas-cli) というツールがある。

使い方はREADMEに書かれてる用例を見ればほとんどわかると思う。

   $ mas list                  #インストールしているストアアプリの一覧を出力
   $ mas search app-name       #ストア上のアプリを名前で検索
   $ mas install app-id-number #ストアアプリをインストール
   $ mas outdated              #更新されているアプリを表示
   $ mas upgrade               #更新されているアプリを最新にする
      :

有償のアプリを購入することはさすがにできないみたい。

個人的にはちょっと前から使っていたのだけど、アプリケーションの指定時に謎の数字(ストア上のURLに含まれるもの)で指示するところとかがどうかなー?と思って公式のリポジトリには登録してなかった。

最近読んだいくつかのMacの環境構築記事で、新しい環境にストアアプリを入れるのに使うということが書かれてて、そういうユースケースならあらかじめ数字わかってるし問題ないと納得したので公式のport登録することにした。

リポジトリ入れてbuildbotの結果ながめるまで気付かなかったのだけど、最新版はswift3で書かれてるからXcode 8以上がいるんだね。OS X 10.11上でも使えてたからあまり意識してなかった。

ということでPortfileに制限の記載を追加。

   # requires swift3
   minimum_xcodeversions {15 8}
   pre-fetch {
       if {${os.major} < 15} {
           ui_error "${name} @${version} requires OS X 10.11 or later."
           return -code error "incompatible OS X version"
       }
   }

これで、Xcode 7.xな環境だとちゃんとバージョンが足りてない旨のメッセージが出るようになる。

   --->  Extracting mas
   Error: On macOS 10.11, mas @1.3.1 requires Xcode 8 or later but you have Xcode 7.3.
   Error: See https://guide.macports.org/chunked/installing.xcode.html for download links.
   Error: org.macports.extract for port mas returned: incompatible Xcode version
   Please see the log file for port mas for details:
       /opt/local/var/macports/logs/_Users_kimuraw_work_ports_sysutils_mas/mas/main.log
   To report a bug, follow the instructions in the guide:
       http://guide.macports.org/#project.tickets
   Error: Processing of port mas failed

2016-11-19

[]MacPortsのw3mmanが動かないので直した

w3mというターミナル上で動作する偉大なブラウザがあってですね、それに付属する`w3mman`というコマンドがSEE ALSOやヘッダファイルをリンクとしてジャンプできたりとえらく便利で愛用してたんですよ。

いつのまにか実行しても空の画面しか表示されなくなっていて、「ながいこと更新されてないソフトだししゃーないな」と思ってエイリアス解除して忘れてしまっていた。さいきんふと思い出して調べてみたら、

   % perl w3mman2html.cgi
   Can't use 'defined(%hash)' (Maybe you should just omit the defined()?) at w3mman2html.cgi line 223.
   %

と、そもそもスクリプトperlのエラーで動かないということがわかった。どうもメッセージのとおり単にdefined()を外せばよいようで、@msmhrtさんからdebian版は問題ないらしいとの情報をもらって確認したりして対応した。

port:w3mはnomaintainerなので修正パッチを追加(ついでにw3mhelp.cgiも)してコミット。

というわけで、port:w3m @0.5.3_6からはw3mmanが動くようになっているはずです。

2016-11-11

[]poll(2)の動作がSierraで変わってるぽい

(2016-11-12追記)この現象は10.12.2 beta2(16C41b)で直っているようです。10.12.2がリリースされたら解消するかもしれません。

ruby 2.4-preview3が出たので、test-all流して動作確認してたら、Sierraで通らないテストがあったので気付いた。

pollのman見ると、poll(2)のインターフェイスはこんななんだけど

   SYNOPSIS
        #include <poll.h>

        int
        poll(struct pollfd fds[], nfds_t nfds, int timeout);

呼び出し時に渡すnfdsの値(=fdsの数)が0のときの動作がSierraから変わっているみたいで

  • 10.11以前: timeoutだけ待つ
  • 10.12: 待たずにすぐ終了する

となっている。

curlのほうでも先月に話題になっていたよう。

Hacker Newsでは「そもそもPOSIX的にどうなん」「仕様的にセーフだったとしてもこれはダメだろ」みたいな議論をしてるっぽいがよくわからん。

Sierraのxnuのソースコードがまだopensource.apple.comにあがってないのがコードみて確認できないのがもどかしい。

この件はruby側の問題じゃないと思うのだけれど、テスト通らないのは動作確認で困るので報告しておいた。

問題のtest/fiddle/test_function.rbを元に、ruby+fiddleでpollの動作確認用のスクリプトを書いた。

   require 'fiddle/import'
   require 'tempfile'

   include Fiddle

   libc = dlopen('/usr/lib/libc.dylib')
   @func = Function.new(libc['poll'], [TYPE_VOIDP, TYPE_INT, TYPE_INT], TYPE_INT)

   def test_poll(fds, nfds)
       t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
       n1 = @func.call(fds&.to_ptr, nfds, 200)
       t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
       puts "fds=#{fds ? fds.fd : "(nil)"}, nfds=#{nfds}, slept=#{t1 - t0}, status=#{n1}"
   end

   fds = Fiddle::Importer.struct(["int fd", "short events", "short revents"]).malloc
   file = Tempfile.open('poll')
   begin
       fds.fd = file.fileno
       fds.events = 0
       fds.revents = 0

       puts RUBY_DESCRIPTION
       puts `uname -sr`.chomp
       test_poll(fds, 0) # not block on macOS Sierra
       test_poll(fds, 1)
       test_poll(nil, 0)
       test_poll(nil, 1)
   ensure
       file.unlink
   end

SierraおよびEl Capitanでの結果は次のとおり。

   # Sierra
   ruby 2.4.0preview3 (2016-11-07 trunk 56661) [x86_64-darwin16]
   Darwin 16.1.0
   fds=7, nfds=0, slept=0, status=0
   fds=7, nfds=1, slept=205, status=0
   fds=(nil), nfds=0, slept=0, status=0 # ←nfds=0では待たない
   fds=(nil), nfds=1, slept=0, status=-1

   # El Capitan
   ruby 2.4.0preview3 (2016-11-07 trunk 56661) [x86_64-darwin15]
   Darwin 15.6.0
   fds=7, nfds=0, slept=201, status=0
   fds=7, nfds=1, slept=206, status=0
   fds=(nil), nfds=0, slept=203, status=0 # ←nfds=0でも待つ
   fds=(nil), nfds=1, slept=0, status=-1
   # Sierra 10.12.2 beta2 (16C41b) INS 2016-11-12
   ruby 2.4.0preview3 (2016-11-07 trunk 56661) [x86_64-darwin16]
   Darwin 16.3.0
   fds=7, nfds=0, slept=201, status=0
   fds=7, nfds=1, slept=202, status=0
   fds=(nil), nfds=0, slept=200, status=0 # 直ってる!?
   fds=(nil), nfds=1, slept=0, status=-1

待たずに終わったときのpoll()の戻り値が0なのもちょっと嫌な感じ。

正直よく知らないのだけど、fd渡さずに単に指定した時間待たせるためにpoll(2)使うのって一般的なテクニックなんですかね?

とりあえずAppleバグとして報告したほうがよさそうだけど、再現コードをCで書き直すのめんどいなあ。(次の10.12.2で直るみたい)

2016-10-26

[] MacPortsの開発リポジトリgithubへ移行(予定)

話はずいぶん前から出てたのだけれど、ようやくMacPortsの開発がgithubに移ることになったそうです。今週末の10/29-30で移行する予定らしい。

今まではmacports.org上のsvntrac上で作業してたけれど、ちょくちょくtracが落ちてたのでgithub.comのほうが稼働率高そうなのがいちばん助かるかなあ。coreはともかくportfileは単純なものだからvcsはsvnでもそんなに困らんし。

コミッタのみなさまMLでの指示(”Moving to GitHub: Status Update, Action Required”)どおり

  • (なければ)githubのアカウントを登録
  • アドレスに macports.org のメールアドレスを追加
  • macports-infra あてに"Please invite me to MacPorts on GitHub"の件名でメール送る

の手続きをとってねとのこと。てゆかさ、ふつうに開発者MLに流れてたから見逃してたよ!

2016-01-01

[][]MacPortsのport:ruby23を登録

例によってクリスマスに新しいバージョンがリリースされていたので対応しました。従来通り、MacPorts版は

  • ruby2.3, rake2.3, gem2.3などバージョンのsuffixがつく
  • port select ruby ruby23などselectを使うと、suffixなしのバージョンで使える

となっています。


Yosemite環境でのコンパイルエラー調査

portへのコミットはわりとすぐやってたんだけど、OS X 10.10 Yosemite環境のbuildbotがエラーはいてて、手元で再現できなかったりと調べてるうちに年が明けてしまった。。

buildbotのエラー

エラー箇所の抜粋。

   compiling regerror.c
   compiling regexec.c
   Stack dump:
   0.	Program arguments: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -cc1 -triple x86_64-apple-macosx10.10.0 -emit-obj -disable-free -disable-llvm-verifier -main-file-name regexec.c -mrelocation-model pic -pic-level 2 -mdisable-fp-elim -masm-verbose -munwind-tables -target-cpu core2 -target-linker-version 242.2 -dwarf-column-info -coverage-file /opt/local/var/macports/build/_opt_mports_dports_lang_ruby23/ruby23/work/ruby-2.3.0/regexec.o -resource-dir /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.1.0 -D _FORTIFY_SOURCE=2 -D RUBY_EXPORT -D _XOPEN_SOURCE -D _DARWIN_C_SOURCE -D _DARWIN_UNLIMITED_SELECT -D _REENTRANT -I /opt/local/include -I /opt/local/include -I . -I .ext/include/x86_64-darwin14 -I ./include -I . -I/opt/local/include -Os -fdebug-compilation-dir /opt/local/var/macports/build/_opt_mports_dports_lang_ruby23/ruby23/work/ruby-2.3.0 -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -fwrapv -stack-protector 1 -mstackrealign -fblocks -fobjc-runtime=macosx-10.10.0 -fencode-extended-block-signature -fmax-type-align=16 -fno-common -fdiagnostics-show-option -vectorize-loops -vectorize-slp -o regexec.o -x c regexec.c
   1.	&lt;eof&gt; parser at end of file
   2.	Per-module optimization passes
   3.	Running pass &#39;CallGraph Pass Manager&#39; on module &#39;regexec.c&#39;.
   4.	Running pass &#39;Loop Pass Manager&#39; on function &#39;@match_at&#39;
   5.	Running pass &#39;Loop Invariant Code Motion&#39; on basic block &#39;%4037&#39;
   clang: error: unable to execute command: Segmentation fault: 11
   clang: error: clang frontend command failed due to signal (use -v to see invocation)
   Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
   Target: x86_64-apple-darwin14.5.0
   Thread model: posix
   clang: note: diagnostic msg: PLEASE submit a bug report to http://developer.apple.com/bugreporter/ and include the crash backtrace, preprocessed source, and associated run script.
   clang: note: diagnostic msg:

regexec.cのコンパイルでエラーでて失敗してる。あんま見たことないケースだなあ。手元の環境で確認したときは問題なかったし、rubyciもgreenだし。

あれこれ試して、以下の場合で再現することがわかった。

のときがアウトっぽい。なんかすごくコンパイラのバグっぽいのですけど。。。

とりあえずPortfileで上記に該当する場合は、最適化フラグを-Osから-O3に書き換えすることで対応することにした。

2015-12-20

[][]MacPortsのport:ruby22, ruby21, ruby20を更新

あたらしいバージョンがリリースされていたので対応しました。今回のバージョンはセキュリティ修正(CVE-2015-7551: Fiddle と DL における tainted 文字列使用時の脆弱性について)が含まれています。

以下自分ようのメモ。


2.2 Leopard以前にlibunwind.hがない?

2.2.3が古いOS X(10.5 Leopard以前)でコンパイルエラーがあるらしくパッチが当てられていたけれど、2.2.4ではupstreamで対応された(Bug #11591)ので削除。


2.2, 2.1 仮想マシン上のtest/ruby/test_io.rbでTypeError

先週ようやく10.11に上げたので、10.10の検証(インストールの確認とtest-all流す)はVMWare上の仮想マシンでやった。

2.2.4と2.1のtest-allでTestIOでエラーが4件出る。

     1) Error:
   TestIO#test_close_on_exec:
   TypeError: no implicit conversion from nil to integer

rubyciではOS X上の2.2/2.1はtest-allのエラーはないので、環境かMacPortsのビルドの問題かなあと考えて調べてみる。

まずはport使わずにふつーにconfigure && make。再現することを確認。2.2.3ではテストをパスすることも確認。

2.2.3と2.2.4でconfig.hを比較、上述のlibunwind.hの件だけで関係なさそう。

   --- .ext/include/x86_64-darwin14/ruby/config.h	2015-12-20 01:34:06.000000000 +0900
   +++ ../ruby-2.2.4/.ext/include/x86_64-darwin14/ruby/config.h	2015-12-20 01:07:06.000000000 +0900
   @@ -332,6 +332,7 @@
    #define SET_THREAD_NAME(name) pthread_setname_np(name)
    #define DEFINE_MCONTEXT_PTR(mc, uc) mcontext_t mc = (uc)->uc_mcontext
    #define HAVE_EXECINFO_H 1
   +#define HAVE_LIBUNWIND_H 1
    #define HAVE_BACKTRACE 1
    #define BROKEN_BACKTRACE 1
    #define DLEXT_MAXLEN 7

次にテストスクリプトを比較、RLIMITまわりの設定が追加されてるね。

   --- ../ruby-2.2.3/test/ruby/test_io.rb      2015-08-14 00:53:27.000000000 +0900
   +++ test/ruby/test_io.rb    2015-12-20 10:51:14.000000000 +0900
   @@ -1065,7 +1065,9 @@
      def ruby(*args)
        args = ['-e', '$>.write($<.read)'] if args.empty?
        ruby = EnvUtil.rubybin
   -    f = IO.popen([ruby] + args, 'r+')
   +    opts = {}
   +    opts[:rlimit_nproc] = 1024 if defined?(Process::RLIMIT_NPROC)
   +    f = IO.popen([ruby] + args, 'r+', opts)
        pid = f.pid
        yield(f)
      ensure
   @@ -1120,6 +1122,10 @@

      def test_dup_many
        ruby('-e', <<-'End') {|f|
   +      if defined?(Process::RLIMIT_NOFILE)
   +        lim = Process.getrlimit(Process::RLIMIT_NOFILE)[0]
   +        Process.setrlimit(Process::RLIMIT_NOFILE, [lim, 1024].min)
   +      end
          ok = 0
          a = []
          begin

試してみた感じだと

   opts[:rlimit_nproc] = 1024 if defined?(Process::RLIMIT_NPROC)

ここの"1024"が環境の最大値を超えてるとだめっぽい。

   # OS X 10.11.2 実機
   % ruby2.2 -e 'p Process.getrlimit(Process::RLIMIT_NPROC)'
   [709, 1064]
   # OS X 10.10.5 VMWare fusion
   % ruby2.2 -e 'p Process.getrlimit(Process::RLIMIT_NPROC)'
   [266, 532]

仮想のほうで1024を532にするとテストをパスするようになる。533だとエラーになる。

ruby本体の問題ではなさそうなのでとりあえず無視することに。ちゃんと調べたらbugs.r-l.oにレポートだそう。

(2015-12-22 追記)Bug #11852として報告して、送ったパッチもマージされた。ありがとうございます!


2.0.0 rubygems/test_gem_remote_fetcher.rbで"dh key too small"

例によってopensslのバージョンが上がったことで要求されるサイズが増えたみたい。

test_gem_remote_fetcher.rbの`OpenSSL::PKey::DH.new(128)`を256にしてみたけど、test-allで流すとエラーのぜんぶは解消できなくってめんどうになってあきらめた。

2015-09-26

[] RubyCocoa 今日のコミット 2015-09-26

以前に見つかっていたバグがよくわからないけど直った。ひさしぶりにぜんぶテストが通るようになったぜ。。

  • NSArrayController#arragendObjects#eachするとruby-2.xだけNSGenericExceptionが起きるのを修正(beca6d4)

rubycocoa issue#2に書いたとおりなんだけど、

   require 'osx/cocoa'
   ctl = OSX::NSArrayController.alloc.init
   content = [1,2,3,4,5].map {|i| i.to_s}
   ctl.addObjects(content)

   p ctl.arrangedObjects
   # expects ["1", "2", "3", "4", "5"]
   # but ruby-2.0 fail with the following error:
   # /Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/oc_wrapper.r
   # b:55:in `ocm_send': NSGenericException - *** Collection <_NSControllerArrayP
   # roxy: 0x7f8e04a66b00> was mutated while being enumerated. (OSX::OCException)

と、ruby-2.x上でObjective-C側の例外が起きてしまう。もちろんふつうのNSArrayは問題ない。

NSArray#eachは

   iter = self.objectEnumerator
   while obj = iter.nextObject
     yield obj
   end

といった感じで実装されていてenumeraterまわしてるだけなので、コレクションのオブジェクトを変更をしているとは思えない。そもそもruby-1.8のときは問題ないしねえ。。

あれこれ調べてたんだけどけっきょく原因はわからなくて、「動かないよりはいいか」とコレクションかイテレータのクラスかなんかで判定してダメそうな場合は

   self.count do |i|
     yield self[i - 1]
   end

みたいにぐるぐるすればよいかと思って試していたら、iter.classNameを呼び出すと元々の実装でも動くようになったことに気付いた。なんだかわからんけど、Objective-CのメソッドをnextObejctの前に呼び出してやればよさそうなことがわかったのでとりあえずそれで対応した。

2015-09-19

[] OS Xの"DYLD_*"環境変数

先日のCocoa勉強会で話してきたので整理しとく。


まとめ

  • dyldはdarwin(OS X, iOS)のld(1)。
  • ldのLD_*環境変数と同様に、DYLD_*環境変数で動作を制御できる。
  • OS X 10.11では、DYLD_*環境変数が無効にされるケースがある見込みだぜ。

dyldと"DYLD_"ではじまる環境変数

dyldはOS X/iOSのダイナミックリンカで、ライブラリフレームワークをロードするプログラムです。man DYLD(1)にあるように、"DYLD_"ではじまる環境変数で動作を変更することができます。UnixLinuxLDでいうところのLD_LIBRARY_PATHやLD_PRELOADの類ですね。

すっごく雑に分けると、これらの環境変数は

  • ライブラリの探索方法を指示
    • DYLD_*_PATH: 探す場所を指示する。
    • DYLD_IMAGE_SUFFIX: デバッグ用などに用意したライブラリのsuffixを指示する。
  • 実行中の情報を表示
    • DYLD_PRINT_*: ロードしたものや実行環境の情報などを標準エラー出力に表示する。
  • その他
    • DYLD_INSERT_LIBRARIES: LD_PRELOAD
    • DYLD_FORCE_FLAT_NAMESPACE, DYLD_BIND_AT_LAUNCH: リンカの解決方法を指定する。

という感じになります。

RubyCocoaの開発ではテストスクリプトの実行時に

  • DYLD_FRAMEWORK_PATH: 開発中のRubyCocoa.frameworkの場所を指示する。
  • DYLD_PRINT_LIBRARIES_POST_LAUNCH: テストスクリプトが正しく開発中のRubyCocoa.frameworkやrubycocoa.bundleをロードしたかを確認する。

の2つを使っています。プログラム的には次のようなrubyスクリプトです。

   ENV['DYLD_FRAMEWORK_PATH'] = path_to_devel_framework
   ENV['DYLD_PRINT_LIBRARIES_POST_LAUNCH'] = '1'
   libs = Open3.popen3("ruby -rosx/cocoa -e ''") do |stdin, stdout, stderr|
     # read stderr
   end
   # test loaded rubycocoa framework/bundle paths from stderr

DYLD_PRINT_LIBRARIESとDYLD_PRINT_LIBRARIES_POST_LAUNCHのちがいは、プロセスの起動時にロードしたものを表示するか否かです。

   % DYLD_PRINT_LIBRARIES=YES ruby2.2 -e 'require "zlib"'
   dyld: loaded: /opt/local/bin/ruby2.2
   dyld: loaded: /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
   dyld: loaded: /opt/local/lib/libruby.2.2.0.dylib
   dyld: loaded: /usr/lib/libSystem.B.dylib
     :
   dyld: loaded: /opt/local/lib/ruby2.2/2.2.0/x86_64-darwin14/enc/encdb.bundle
   dyld: loaded: /opt/local/lib/ruby2.2/2.2.0/x86_64-darwin14/enc/trans/transdb.bundle
   dyld: loaded: /opt/local/lib/ruby2.2/2.2.0/x86_64-darwin14/thread.bundle
   dyld: loaded: /opt/local/lib/ruby2.2/2.2.0/x86_64-darwin14/date_core.bundle
   dyld: loaded: /opt/local/lib/ruby2.2/2.2.0/x86_64-darwin14/zlib.bundle
   dyld: loaded: /opt/local/lib/libz.1.dylib
   % DYLD_PRINT_LIBRARIES_POST_LAUNCH=YES ruby2.2 -e 'require "zlib"'
   dyld: loaded: /opt/local/lib/ruby2.2/2.2.0/x86_64-darwin14/enc/encdb.bundle
   dyld: loaded: /opt/local/lib/ruby2.2/2.2.0/x86_64-darwin14/enc/trans/transdb.bundle
   dyld: loaded: /opt/local/lib/ruby2.2/2.2.0/x86_64-darwin14/thread.bundle
   dyld: loaded: /opt/local/lib/ruby2.2/2.2.0/x86_64-darwin14/zlib.bundle
   dyld: loaded: /opt/local/lib/libz.1.dylib
   %

OS X 10.11での制限

そろそろ10.11がリリースされそう(当時beta 8)なのでRubyCocoaの検証をしていたところ、上記のテストスクリプトのフレームワークのパスの検証が通らないことに気付きました。どうもDYLD_FRAMEWORK_PATH環境変数が機能していないようです。

試してみると、

   % uname -r
   15.0.0 # 10.11 GM
   % ruby -e "system({'DYLD_AAA' => 'AAA', 'AAA_DYLD_BBB' => 'BBB'}, \
                 '/usr/bin/printenv | grep DYLD')"
   AAA_DYLD_BBB=BBB
   %

と、"DYLD_"ではじまる環境変数が子プロセスに反映されないようになっているようです。betaの無印のときはこんなことなかったと思うんだけどなあ。もちろんOS X 10.10では"DYLD_AAA"も出力されます。

仕方ないので、次のような一時ファイルのシェルスクリプトを生成して実行することを考えています。

   # temp shell script for testing with DYLD_ environments
   DYLD_FRAMEWORK_PATH=path ${RUBY} -rosx/cocoa -e ''

さすがにこれで解消するのですが、なんかすごく不毛な気持ちになります。もうちょっとスマートに書けるような…

よい方法があれば教えてください!だいぶ切実です。

(2015-09-19追記: ついったで @n0kada さんに`env`コマンドでいけることを教えてもらいました。ありがとうございます!)

また、WWDC 2015のセッション706:”Security and Your Apps”(ASCIIwwdc)で説明されているように、保護される領域(/Systemや/usr/binなど)にあるバイナリではDYLD_*環境変数は問答無用で無視されるようになっています。

例を示すと、

   % uname -r
   15.0.0 # 10.11 GM
   % cat dyld_env.rb
   # print DYLD_* environments
   ENV.each_pair do |k, v|
       puts "#{k}=#{v}" if k =~ /DYLD/
   end
   % DYLD_AAA=AAA AAA_DYLD_BBB=BBB /usr/bin/ruby dyld_env.rb
   AAA_DYLD_BBB=BBB
   % DYLD_AAA=AAA AAA_DYLD_BBB=BBB /opt/local/bin/ruby2.2 dyld_env.rb
   dyld: warning, unknown environment variable: DYLD_AAA
   DYLD_AAA=AAA
   AAA_DYLD_BBB=BBB
   %

のように、システム付属のrubyにはDYLD_ではじまる環境変数が渡されないようになっています。


感想

セキュリティ観点としてはいままでがざるざるだったこともあり、制限は仕方ないし正しい方向だとは思います。だけど、プログラム書く人間としてはめんどくさいなあという気持ちも隠せません。

人によってはぜんぜん影響ないかもしれませんが、思わぬワナにはまるかもなのでご注意を。

[] RubyCocoa 今日のコミット 2015-09-19

10.11GM上で10.10と同じようにテスト通る(既知の1F)まで持ってきた。

作業はビルドまわりとテストスクリプト側の修正でコアの方は手をいれてない。

  • 10.11ではRubyCocoa.frameworkは@excecutable_pathなしをデフォルトに。 (ceb7962)
  • 上述のDYLD_環境変数の件に対応。(c0bd8ae, 095de97)
  • CoreFoundationのretain countのテストが通らないのを修正。てか元のテストの意図がびみょーだったので消した。(56647a4)
  • KeyValueObvervingのテストで観測対象の値を初期化するように。一部のケースでKVO発火時に現在の値を取得するようになったぽい。実際には@value1だけ初期値が必要なんだけどそれも気持ち悪いのでひととおり入れてくようにした。(20133e6)

最初の@excecutable_pathは、OS添付のrubyコマンドから使うときに問題起きないようにするために変更した。

`ruby`から実行するとき、require 'osx/cocoa'でrubycocoa.bundleが読み込まれ、そこからリンクしているRubyCocoa.frameworkがロードされるという順になるのだけれど、このときバイナリに記録されているパスが@excecutable_pathを含んでいると"unsafe use of @executable_path"とのメッセージが表示されロードが中止されてしまう。ということで、/Library/Frameworksがデフォルトになるようにした。

その影響で、今後リリースするだろうパッケージからインストールしたRubyCocoa.frameworkをアプリケーションに同梱するときは単に.frameworkを.appにほうりこむだけではダメで、install_name_toolでライブラリのパスを変更する必要がある。standaloneify.rbを使っている場合はスクリプト側で対処する予定なので、従来どおり使えば問題ない。

現在の構成もわかりづらいしこういう問題もあるので、将来的には

  • rubyコマンドから使う場合はrubycocoa.bundleだけをロードする。
  • .appからはRubyCocoa.frameworkをロードする。

というように住み分けするようにしたほうがよいと考えている。前者だけgemで配布できるようになるし。

2015-08-20

[][]MacPortsのport:ruby22, ruby21, ruby20を更新

あたらしいバージョンがリリースされていたので対応しました。

RubyGemsCVE-2015-3900のセキュリティ修正が含まれてたりします。詳しくは公式のリリースアナウンスをみてください。

また、以前に書いたように、port:ruby22にjemallocバリアントを追加しました。

2015-06-13

[]rubyforgeがもうない件の対応

今はなきrubyforgeの記載がPortfileに大量に残ってるのマズくね?的な話が来てた。

知ってたけどさ!ファイルはmacports.org側で再配布のコピー持ってるしいいじゃん……

とりあえず自分が担当の分だけやってみて、わりといけそうな感触があったので他のも対処。たぶん全部で160 portsくらい直した。

だいたい作業はこんな感じ。

  • 新しいウェブサイトや配布サイトを探して変更
    • rubygems.orgにあるものはそこのhomepageを見て。homepageがなければrubygems.org上のページに。
    • githubから.tar.gz取得するものは、PortGroup githubを使う。便利!!
  • gemでなく、現在の配布サイトが見つからないものは依存してる他のportがないか確認して削除。
    • gemがあるものは依存portもまとめてgem化できれば、rubygems.orgをホームページに変更して存続。
  • インストールできるけれど実行できない、コア機能のテストが通らないものもあっても仕方ないので削除。

ぜんぜん現サイトがわからなくて検索した結果、同名のライブラリあって作者変わってる場合、forkなのか引き継ぎしたのか同名の別ライブラリなのかとかの判定がしんどかった。。

2015-06-12

[] RubyCocoa 今日のコミット 2015-06-12

新しいOS Xbetaが出たので検証中、っていうかSEGVしてテスト走らないじゃん。。

だいたいこういうレベルでおかしいときは、コンパイル時に警告出てたりするものなので確認。

   In file included from /Users/kimuraw/proj/rubycocoa/framework/src/objc/OverrideMixin.m:13:
   In file included from /Users/kimuraw/proj/rubycocoa/framework/src/objc/OverrideMixin.h:10:
   In file included from /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/objc/objc-class.h:1:
   /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/objc/runtime.h:56:11: note: 'isa' has been explicitly marked deprecated here
       Class isa  OBJC_ISA_AVAILABILITY;
             ^
   /Users/kimuraw/proj/rubycocoa/framework/src/objc/OverrideMixin.m:492:22: warning: 'isa' is deprecated [-Wdeprecated-declarations]
     class_addMethod(c->isa, @selector(alloc), (IMP)imp_c_alloc, "@4@4:8");
                        ^

たぶんこれだね。クラッシュレポートもinit_ovmix() -> class_addMethod()のあたりで落ちてるし。クラスのメタクラスを取るのにisa直接見てるけど、だいぶ前にdeprecateされた方法。

objcでメタクラスを取る方法は

  • objc_getMetaClass()にクラス名を渡す。
  • object_getClass()にクラス(Class)を渡す。(ふつうのオブジェクトを渡すとそのクラスが得られる)

のどちらかで、今回はClassはもう用意してあるので後者のほうがよいね。ということで直した。

  • メタクラスの取得方法を改善(8babc63)

まあまだOS X 10.11上でぜんぶのテストは通らないんだけどね!

あとテスト流すと次のようなメッセージがでるので対処しといた。outletへのsetterがないから繋げないぜ、とのこと。

   2015-06-12 01:51:36.174 ruby2.2[1285:2455542] Failed to connect (tableView2) outlet from (TableViewNibOwner) to (NSScrollView): missing setter or instance variable

単に警告の出てたoutletに対してib_outletで宣言するようにした。

  • テスト時の"Failed to connect..."が出ないように。(c8fa6b2

2015-05-31

[]RubyCocoaプロジェクトをgithubに移行

しました。

インストーラは最新の1.2.0 (2014年7月)だけgithubにも置きました。それ以前のはSourceForgeからゲットしてください。

f:id:kimuraw:20150531140505p:image

import.github.com使って、そのまま持ってきたので昔の開発用のタグも混ざって"102 releases"とかワケわかんないことになってますね…

ウェブサイトAPIリファレンスのついでにyardで作ってるんですが、.nojekyllファイルを置かないとIndexナビゲーションが機能しない(_index.html is not working for gh-pages · Issue #111 · lsegal/yard)とかにハマったりしました。

活発とは言えませんが、メンテナンスは続けるつもりなのでよろしくお願いします。

[] RubyCocoa 今日のコミット 2015-05-31

半年ぶりくらいですね。。

rbenvの件で思い出したんだけど、RubyCocoaがruby.dylibを要求するのってなんでなのでしょうね。昔は.aでもよかったし、動作させる上では技術的にも問題ないはずなのでライセンス的な話かなあ。。

2015-05-30

[]rb22-*なportがぜんぜんない

とくに結論のないはなし。

MacPortsにrb22-てportないんだけど、なんか例とかないの?」てメールが来た。

PortGroup rubyの確認用に手元では作ってるので、そいつを簡略化してgistに上げて「これ見て」と返信しておいた。


ruby.setup

MacPortsにはPortGroup(コード)という仕組みがあって、Portfileを簡単に書けるようにいろいろサポートしてくれる。

自分が担当する前(ruby-1.8.6以前のころ)から、PortGroup rubyにはruby.setupキーワード(tcl的にはproc)があって、これを使うと簡単にRubyのライブラリやツールがインストールできるようになっている。

前述のgistの例でいうと、

   ruby.setup          bundler 1.10.1 gem {} rubygems ruby22

で、この行のruby22をruby21にすればport:ruby21用のPortfileになる。(実際にはPortfileのファイル名も変えないとlintにはひっかかる)

これはrubygemsを使う例だけど、他にもいろいろなインストール手法に対応していて、

  • setup.rb
  • extconf.rb && make && make install
  • install.rb (1) basic_install.rb - 実行するとぜんぶインストールする。
  • install.rb (2) - config.saveを生成するタイプ。
  • make (このタイプpdumpfsしか見たことない…)
  • 単純にコピー

などが利用できるようになっている。でもいまどきはgemしかないよね。


rb22-* なportはなぜないのか / そもそもいるの?

直接にはだれもコミットしてないからなわけだけど。いちお考えてみると、

  • brew使ってる
  • gem installすればいい

あたりだよねえ。きっと。

個人的にはgem install|updateすればいいし、portつくって更新に追従するのもめんどう、といったところ。

ただそれは自分がrubyユーザだからそう思うわけで、そうでない人が特定のコマンド使いたいだけで「gem installしてね」というのもどうなんじゃろ?とも思える。(冒頭の質問してきたひとはRailsやってるて書いてたのでgemやbundler使ったほうがよくね?と思うけれど)

たとえばackPerlsphinxblockdiagPythonなわけだけど、それぞれに応じてcpanやpip使いわけてね!ってのものなんだかびみょーな気持ちはぬぐえないよな。

cpan2portのように言語のパッケージシステムから自動でPortfile生成するのもあって、これのgem用のをつくるのもそんな難しくないけど、じゃあ欲しいかっていうとそうでもないよなあ。

2015-05-24

[][]第72回 Cocoa勉強会に行ってきた(5/23)

会場はいつもの新宿伊藤ビルの貸し会議室

ここのとこ休んでたのでわりとひさしぶり。

なんか今回は「Cocoa……?」な回でした。資料はconnpassのほうとか。


発表

業務システム開発の話。自分はそっち側の人間なわけだけど、わかることもそうでないことも。

RSpecに強く影響を受けたテスティングフレームワークQuickの話。ちょうどその後にネット上でまたRSpecについて盛り上がってたのでいいタイミング?

自分はずっとtest-unit派でRSpecよくわからんのだけど、せっかくの機会なので”Better Specs { rspec guidelines with ruby }”とか読んだりしてる。

普段使い+ラズパイ機器の開発にも使える持ち運び可能なディスプレイの話。あいかわらずハードウェアはさっぱりわからん。話聞いてるのは面白いのだけれど。


次回の予定

次回は7月の予定です。

2015-04-15

[][]MacPortsのport:ruby22, ruby21, ruby20を更新

あたらしいバージョンがリリースされていたので対応しました。

  • port:ruby22: 2.2.2
  • port:ruby21: 2.1.6
  • port:ruby20: 2.0.0-p645

2.2にはtk-8.6対応が入ったみたいなんだけど、手元での確認が終わらなかったのでtkバリアントはまだ有効にしていません。次までにはなんとかしたいかな。

あと2.2でサポートしたjemallocもバリアントに次から追加する予定(手元ではテスト済み)です。gmpと同様に、デフォルトはオフで+jemallocで有効になるようにします。