torutkのブログ

ソフトウェア・エンジニアのブログ

Scene Builder 2.0.1をビルドする

この日記は、JavaFX Advent Calendar 2014 - Adventarの3日目です。
昨日はalchemicalogicさんのJavaFXでMMDモデルを表示することにチャレンジした – XiPHiA's noteで、
明日はmike_neckさんのJavaFXで画面を作るときにFXMLを小さく作る #javafx #javafx_ja - mike-neckのブログです。

はじめに

本日のネタは、JavaFX Scene Builder 2.0.1をビルドする、です。

現在リリースされているScene Builder 2.0はJRE 8(1.8.0-b132)を中に含む形で一緒にインストールします。
そのため、JDK 8u20で多数適用されたJavaFX関連修正やJDK 8u40で適用される修正や新たに加わるコントロールなどには対応していません。Scene Builderでプレビューした画面とJDK 8u25などでプログラムを実行した画面とで違いが生じることがあります。

Scene Builder 2.0をWindows OS上へインストールした場合*1、インストールディレクトリの中にruntime\jre というディレクトリがあり、そこにJREが一式入っています。ディレクトリ構成はJREとほぼ同一だったので、安直にこれをJRE 8u25に差し替えてみたところ、Scenen Builderが立ちあがらなくなってしまいました。うーん、どうしたらよいものか・・・とこの数ヶ月思っていました。

先日開催されたJavaFX Nightの懇親会で、JavaFXといえばの櫻庭さんに相談してみたところ、Scene Builderのソースからビルドしてみたらとのヒントをもらい、調べてみました。

JEP 209: JavaFX Scene Builder Update

OpenJDKでは既にJEP(JEPはOpenJDKへの機能追加を管理する機構のようなもの?)としてScene Builderを8u40に対応させる開発が実施されていました。
http://openjdk.java.net/jeps/209

8u40で新たに追加されるコントロールへの対応や操作性の改善などがリストに挙がっています。
ステータスはClosed/Deliveredとなっていました。おや、Delivered?、もしかすると、Scene Builderの2.0.1のPreviewが公開されているのか?と探してみましたが、見つけることはできませんでした。

ですが、ステータスから8u40向けのOpenJDK(OpenJFX)のソースにはおそらくJEP 209が反映されていると思われます。

本記事でのビルド環境

本記事のビルド環境は次のとおりです。

Scene Builderのソースコードを入手する

Scene Builderのソースコードは、OpenJFX(JavaFX自身のオープンソース開発プロジェクト)に含まれるようになっています。OpenJFXのホームページは次のURLのようです。
https://wiki.openjdk.java.net/display/OpenJFX/Main

このページに、マーキュリアル・リポジトリ(8u-dev)のURLが記載されています。
http://hg.openjdk.java.net/openjfx/8u-dev/rt

マーキュリアルでこのリポジトリを入手します。

work$ hg clone http://hg.openjdk.java.net/openjfx/8u-dev/rt
複製先ディレクトリ: rt
全リビジョンを取得中
リビジョンを追加中
マニフェストを追加中
ファイルの変更を追加中
8448 個のリビジョン(81240 の変更を 41981 ファイルに適用)を追加
ブランチ default へ更新中
ファイルの更新数 20508、 マージ数 0、 削除数 0、 衝突未解消数 0
work$

コマンドを実行してから最初のメッセージが出るまでかなり時間がかかるので心配になりますが、あせらずに待ちます。
入手したリポジトリディレクトリ構成は次のようになります。Scene Builderへのパスをドリルダウンした表示としています。

rt/
  +-- apps/
  |     +-- build.xml
  |     +-- experiments/
  |     +-- performance/
  |     +-- samples/
  |     +-- scenebuilder/
  |     |     +-- build.xml
  |     |     +-- .classpath
  |     |     +--  .project
  |     |     +-- samples/
  |     |     +-- SceneBuilderApp/
  |     |     |     +-- build.xml
  |     |     |     +-- manifest.mf
  |     |     |     +-- nbproject/
  |     |     |     +-- src/
  |     |     +-- SceneBuilderKit/
  |     |     |     +-- build.xml
  |     |     |     +-- manifest.mf
  |     |     |     +-- nbproject/
  |     |     |     +-- src/
  |     +-- toys/
  +-- build.gradle
  +-- build.properties
  +-- buildSrc/
  +-- doc-files/
  +-- gradle.properties.template
  +-- LICENSE
  +-- modules/
  +-- netbeans/
  +-- README
  +-- settings.gradle
  +-- tests
  +-- tools

Scene Builderをビルドするには、SceneBuilderAppとSceneBuilderKitの2つが必要になります。
.projectファイルやnbprojectディレクトリがあるとおり、EclipseNetBeansのプロジェクトとして提供されています。

ではさっそくNetBeansでビルド、とする前に、Scene Builder 2.0.1は、JDK 8u40に対応するものなので、JDK 8u40をインストールしておく必要があります。

JDK 8u40(Early Access)のインストール

JDK 8u40 Early Accessの公開ページからJDKをダウンロードしインストールします。
https://jdk8.java.net/download.html

Windows OS用のScene Builderでは、32bit版で作っておくと、32bit版と64bit版のどちらにもインストールできます。そこで、32bit版をインストールします。本日時点では次のようにb16版ですが、1,2週間ごとに新しいビルドが公開されています。

NetBeans 8.0へJDK 8u40の設定

NetBeans 8.0*2の[ツール]メニュー > [Javaプラットフォーム] で「Javaプラットフォーム・マネージャ」ダイアログを開きます。
[プラットフォームの追加...]ボタンを押し、「Javaプラットフォームの追加」ダイアログを開きます。[プラットフォーム・フォルダを選択]で、先ほどインストールしたJDK 8u40のディレクトリを指定します。[プラットフォーム名]は適当に、例えば"JDK 8u40(32bit)"と指定します。

Scene Builderをビルド

NetBeansから、SceneBuilderAppとSceneBuilderKitの2つのプロジェクトを開きます。
プロジェクトを開くときに「プロジェクトの問題」警告ダイアログが出ますが、これはOpenJFXのソースコードNetBeansプロジェクト定義で使用するJavaプラットフォームの参照名が"JDK_8"となっていますが、NetBeans 8.0のJavaプラットフォーム定義に"JDK_8"が存在しないためです。
そこで、SceneBuilderAppとSceneBuilderKitのそれぞれについて、プロジェクトのプロパティを開き、左側ペインの[カテゴリ]欄で[ライブラリ]を選択、右側ペインの[Javaプラットフォーム]に先ほど作成した[JDK 8u40(32bit)]を選択します。

これで参照問題が解決されました。SceneBuilderAppプロジェクトの設定でSceneBuilderKitを参照するようになっているので、SceneBuilderAppプロジェクトを選択してビルドします。
何事もなくビルド成功となり、SceneBuilderAppプロジェクトを実行すると、SceneBuilderが立ち上がります。

左側のパレットに、JDK 8u40で追加されたダイアログ等が見受けられます。

ビルド成果物

SceneBuilderAppプロジェクトの下に、ビルドした成果物が次のように置かれます。

SceneBuilderApp
  +-- dist
        +-- SceneBuilderApp.jar
        +-- lib
              +-- SceneBuilderKit.jar

JDK 8u40 または JRE 8u40 でSceneBuilder.jarを実行するとSceneBuilderが立ち上がります。
dist以下をコピーすれば別のマシンでScene Builderが立ち上がります。

SceneBuilderApp.jarは実行可能JAR形式ですが、マシンのデフォルトのJREが8u40でないと動かないので、そのときはコマンドライン等でJDK/JRE 8u40へパスを通してjavaコマンドで実行します。

Scene Builderインストーラ形式の作成

NetBeansでSceneBuilderAppプロジェクトのプロパティを開き、左側ペインの[カテゴリ]で[デプロイメント]を選択、右側ペインで[プロジェクト・メニューでネイティブ・パッケージング・アクションを有効化]にチェックを付けます。

SceneBuilderAppプロジェクトを右クリックし、[パッケージとして] をクリックすると、サブメニューで次のメニュー項目が表示されます。

インストーラを作るには、所定のインストーラ作成ツールをインストールしておく必要があります。Windows OSでは、EXE形式インストーラを作成するには「Inno Setup」を、MSI形式インストーラを作成するには「WiX Toolset」が必要になります。

[イメージのみ]は、実行に必要となるファイル(JRE含めて)を一つのディレクトリツリーに集めたもので、これをZIPで固めて配布というのが可能です。
以下に、[イメージのみ]を生成したときのディレクトリツリーを示します。

SceneBuilderApp
  +-- dist
        +-- bundles
              +-- SceneBuilderApp
                    +-- SceneBuilderApp.exe
                    +-- SceneBuilderApp.ico
                    +-- app 
                    |     +-- SceneBulderApp.jar
                    |     +-- package.cfg
                    |     +-- lib
                    |           +-- SceneBuilderKit.jar
                    +-- runtime
                          +-- jre
                                +-- bin
                                +-- lib
                                 :

本日の記事では、時間切れで(MSI形式のインストーラ作成に難航して・・・)、EXE形式、MSI形式までは述べることができませんでした。近日リベンジしたいと考えております。

インストーラ形式の作成(追記)

EXEインストーラ

Inno Setupをインストールしていると、[EXEインストーラ]を選択してEXE形式のインストーラを作成することができます。Inno Setupは以下URLから入手できます。
http://www.jrsoftware.org/isdl.php

環境変数PATHにInno Setupのコマンドが通るように設定するとNetBeansからInno Setupを利用してEXE形式のインストーラを生成します。

SceneBuilderApp
  +-- dist
        +-- bundles
              +-- SceneBuilderApp-1.0.exe

この"SceneBuilderApp-1.0.exe"を実行すると、インストーラが立ち上がり、次のディレクトリにインストールします。

C:\Users\<ユーザー名>\AppData\Local\SceneBuilderApp
  +-- app
  |     +-- lib
  |     |     +-- SceneBuilderKit.jar
  |     +-- package.cfg
  |     +-- SceneBuilderApp.jar
  +-- runtime
  |     +-- jre
  |           +-- bin
  |           +-- lib
  :           :
  +-- SceneBuilderApp.exe
  +-- SceneBuilderApp.ico
  +-- unins000.dat
  +-- unins000.exe

また、スタートメニューにも、[Oracle] > [SceneBuilderApp] として追加されています。

EXEインストーラでインストールしたら立ち上がらない

作成したEXEインストーラをインストールし、SceneBuilderAppを起動すると、エラーとなりました。「Failed due to exception from main class.」
runtime/jre/binにあるDLL(java.dllなど)をエクスプローラで右クリック > プロパティ > 詳細 でみると製品名がJava(TM) Platform SE 8 U25となっています。ビルドしたPCには、Java 8u11, 8u20, 8u25, 8u40が入っているので、どうやら8u25のJREがバンドルされてしまっているようです。NetBeansのビルドログをよく調べると、

Launching <fx:deploy> in native packager mode...
ベースJDKがありません。パッケージはシステムJREを使用します。
Installer (.exe) saved to: C:\Users\foo\Documents\work\scenebuilder\SceneBuilderApp\dist\bundles

というメッセージがあります。設定が追加で必要そうです。EXEインストーラ作成はここで断念。

MSIインストーラ

WiX Toolsetをインストールしていると、[MSIインストーラ]を選択してMSI形式のインストーラを作成することができます。WiX Toolsetは以下URLから入手できます。
http://wixtoolset.org/

環境変数PATHにWiX Toolsetのコマンドが通るように設定するとNetBeansからWiX Toolsetを利用してMSI形式のインストーラを生成します。

JavaFX native packager requires external WiX 3.0+ tools installed and included on PATH
 to create MSI installer. See http://wix.sourceforge.net/

WiXのバージョン3.0以降が見つからないよといっています。WiX 3.8が入っているしPATHも通っているので原因を調べてみると、build-native.xmlの-check-WiX-presenseターゲットの定義の中に次の記述がありました。

 <exec executable="candle" outputproperty="exec-output" failifexecutionfails="false" errorproperty="exec-error" resultproperty="exec-result">
    <arg value="-?"/>
</exec>
    :中略
<condition property="missing.WiX">
    <not><and>
        <contains string="${exec-output}" substring="Windows Installer Xml Compiler version"/>
        <not><contains string="${exec-output}" substring="Windows Installer Xml Compiler version 1"/></not>
        <not><contains string="${exec-output}" substring="Windows Installer Xml Compiler version 2"/></not>
    </and></not>
</condition>

candle.exe -? を実行し、出力されるメッセージを解析し、"Windows Installer Xml Compiler version"文字列を見つけてバージョン判別をしています。
ところが、WiX 3.8のcandle.exeを実行すると

C:\>candle
Windows Installer XML Toolset Compiler version 3.8.1128.0
Copyright (c) Outercurve Foundation. All rights reserved.

と、メッセージ文字列に"Toolset"が増えているのでバージョン判別に失敗していることが分かります。

OpenJFXのSceneBuilderのNetBeansプロジェクトは少し古いバージョン(NetBeans 7.x)で作ったもののようです。

バンドルされるJREが8u40のもにならない問題についてはEXEインストールと同じです。

今日はここまで・・・

*1:Linux版も同様と思われます

*2:本日時点で8.0.2が最新版です