ござるのブログ

覚え書きいろいろ

Ruby/TkでTk拡張を使っているRubyスクリプトをexe化

はじめに

Ruby/TkとTk拡張で作ったちょっとしたツールWindows利用者に使ってもらう場合、RubyやTk拡張をインストールしてもらう必要があり、気軽に使ってもらうのは難しいです。そこでocraを使って単一のexeファイルにしたのですが、結構てこずりました。

RubyとActiveTclとTk拡張(Plotchart)のインストール

RubyActiveTclのインストールについては前の記事を見てください。

Plotchartは、前の記事ではteacupでインストール後C:\Ruby21\lib\ruby\2.1.0\tkextlib\setup.rbを編集してRuby/Tkに認識させましたが、これだとC:\Tcl\lib\teapot\package\tcl\lib\Plotchart2.3.3C:\Ruby21の外にあるため(?)、ocraでexe化する時に取り込まれません。

そこでsetup.rbは編集せず、Plotchart2.3.3フォルダごとC:\Ruby21\lib\tcltk内にコピーしました。C:\Ruby21\lib\tcltk内は、下記のような感じになります。

f:id:gzalt:20150216215501p:plain

ocraのインストール

「スタートメニュー」→「Ruby 2.1.5p273」→「Rubyコマンドプロンプトを開く」から

C:\Users\hoge>gem install ocra

と入力しocraをインストールしますが、

ERROR:  Could not find a valid gem 'ocra' (>= 0), here is why:
          Unable to download data from https://rubygems.org/ - SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (https://api.rubygems.org/latest_specs.4.8.gz)

と言われるかもしれません。これはバグらしいので、こちらのサイトの記載の通りここにあるAddTrustExternalCARoot-2048.pemC:\Ruby21\lib\ruby\2.1.0\rubygems\ssl_certsにコピーして、再度試してください。

ocraでexe化

無事ocraがインストールできたら、こちらのサイトを参考に、前の記事スクリプトをexe化してみます。

C:\Users\hoge>ocra plot.rbw C:\Ruby21\lib\tcltk --no-autoload --add-all-core

うまくいきましたと言いたいところですが

C:/Users/hoge/plot.rbw:18:in `<top (required)>': uninitialized constant DATA (NameError)

と言われるので、少しコードを修正します。

#!/usr/bin/env ruby
# -*- coding: utf-8 -*-

require 'csv'
require 'tk'
require 'tkextlib/tcllib/plotchart'

# plotchart.rb を修正するモンキーパッチ
module Tk::Tcllib::Plotchart
  class XYPlot
    def pixel_to_coords(x, y)
      list(tk_call_without_enc('::Plotchart::pixelToCoords', @path, x, y))
    end
  end
end

# データ
data = <<EOS
32.78,1074
62.72,12131
92.70,13944
122.72,13110
152.79,11859
182.90,13204
213.05,11647
243.24,8780
273.47,7412
303.75,6632
334.07,6460
364.43,6369
394.83,6503
425.28,6566
455.76,5250
486.29,2766
516.86,1574
547.48,1062
578.13,914
608.83,3532
639.57,15018
670.35,18992
701.18,6495
732.04,660
762.95,177
793.90,157
824.89,134
855.93,154
887.00,131
918.12,124
949.28,129
980.48,113
1011.73,96
1043.01,103
1074.34,112
1105.72,92
1137.13,95
1168.58,86
1200.08,85
1231.62,66
1263.20,50
1294.83,29
1326.49,40
1358.20,33
1389.95,47
1421.74,93
1453.57,111
1485.45,67
1517.37,41
1549.33,19
1581.33,17
1613.38,11
1645.46,13
1677.59,18
1709.76,15
1741.98,10
1774.23,6
1806.53,13
1838.87,15
1871.25,11
1903.67,6
1936.14,8
1968.64,6
2001.20,8
EOS

# データを読み込み
en, cn = CSV.parse(data).map { |r| [r[0].to_f, r[1].to_i] }.transpose

# データをプロット
pl = Tk::Tcllib::Plotchart::XLogYPlot
     .new([0, en.size, 10**Math.log10(en.size).floor],
          [1, 10**Math.log10(cn.max).ceil],
          width: 600, height: 400) do
  title 'Spectrum'
  xtext 'Channel'
  ytext 'Counts/Channel'
  dataconfig('series1', color: :red)
  cn.each_with_index { |c, i| plot('series1', i, c) }
  pack(fill: :both)
end

# マウスの位置の値の表示
label = TkLabel.new.pack
pl.bind(:Motion, '%x %y') do |x, y|
  ch = pl.pixel_to_coords(x, y)[0].to_i
  if 0 <= ch && ch < en.size
    label.text(sprintf('%10d ch, %10.1f keV, %10d counts',
                       ch, en[ch], cn[ch]))
  end
end

# イベントループ
Tk.mainloop

再度exe化を試みます。

C:\Users\hoge>ocra plot.rbw C:\Ruby21\lib\tcltk --no-autoload --add-all-core

グラフが表示されるので[x]をクリックして終了させると、以下のようにうまくexe化されました。

f:id:gzalt:20150216222753p:plain

サイズは5.14MBになりました。

実行結果

できあがったexeをダブルクリックすると、下記のようなグラフが表示されます。

f:id:gzalt:20150216124756g:plain

RubyActiveTclがインストールされていないWindows環境でも動作するはずです。

最後に

ちょっと大変でしたが、一度やればいいことなので、まあいいか。