ARMアーキテクチャ環境のJava7でRXTXをビルドする。

RXTX http://rxtx.qbang.org/wiki/index.php/Main_Page

OpenBlocksAX3にRXTXをインストールする時にハマった内容。
OpenBlocksAX3はarmv7lと言うアーキテクチャを使用しているので、
RXTXでダウンロードできるバイナリをそのままJRE配下へ持っていっても動かない。
以下のようなエラーが出る。


java.lang.UnsatisfiedLinkError: /usr/lib/jre/lib/arm/librxtxSerial.so: /usr/lib/jre/lib/arm/librxtxSerial.so: cannot open shared object file: No such file or directory (Possible cause: can't load IA 32-bit .so on a ARM-bit platform) thrown while loading gnu.io.RXTXCommDriver

これはarmv7l上でi686用のlibrxtxSerial.soを呼んでいるためであって、armv7l用のlibrxtxSerial.soを用意してやる必要がある。
Jim Connors' Weblog(https://blogs.oracle.com/jtc/entry/serial_port_communication_for_java)にビルド済みのarm用librxtxSerial.soが公開されているので、そこから取得すれば問題なく動作してくれる。

動作してくれるのだが、Java6でビルドしてあり、Java7で動かすにはどうにも気持ち悪いし、今後も同様に動作してくれるのか怪しいので、ソースからビルドする。
まず、OpenBlocksにはJREしか入っていないので、このJREを無効にする。
■すべてコメントアウトする。


$ sudo vi /etc/profile.d/java.sh
#JAVA_HOME=/usr/lib/jre
#PATH=$PATH:$JAVA_HOME/bin
#export JAVA_HOME PATH

■再起動する。


$ sudo reboot
javaコマンドが無効になっていることを確認。

$ java -version
bash: java: command not found

OracleよりARMアーキテクチャ用のJDK7をダウンロードする。
Linux ARM v6/v7 Soft Float ABI(jdk-7u21-linux-arm-sfp.tar.gz)

■解凍して/usr/localへコピー。


$ tar zxvf jdk-7u21-linux-arm-sfp.tar.gz
$ sudo cp -R ./jdk1.7.0_21 /usr/local/
■update-alternatives --installでjava、javacを登録する。

$ sudo update-alternatives --install /usr/bin/java java /usr/java/jdk1.7.0_21/bin/java 1
$ sudo update-alternatives --install /usr/bin/javac javac /usr/java/jdk1.7.0_21/bin/javac 1
■確認

$ java -version
java version "1.7.0_21"
Java(TM) SE Runtime Environment (build 1.7.0_21-b11)
Java HotSpot(TM) Client VM (build 23.21-b01, mixed mode)
$ javac -version
javac 1.7.0_21

RXTXからSource(rxtx-2.1.7r2.zip)をダウンロードし、解凍する。
■unzipコマンドをインストール


$ sudo aptitude install unzip
■解凍する。

$ unzip rxtx-2.1-7r2.zip
$ cd rxtx-2.1-7r2/
Installationを見ながら何も考えずにビルドを行う。

$ ./configure
$ make
Javaディレクトリ配下へコピーする。(シンボリックリンク張るのも忘れずに)

$ sudo cp RXTXcomm.jar /usr/local/jdk1.7.0_21/jre/lib/ext/
$ sudo cp ./armv7l-unknown-linux-gnu/.libs/librxtxSerial-2.1-7.so /usr/local/jdk1.7.0_21/jre/lib/arm/
$ sudo ln -s librxtxSerial-2.1-7.so librxtxSerial.so

そうすると以下のエラーが出る。


java.lang.UnsatisfiedLinkError: gnu.io.RXTXCommDriver.nativeGetVersion()Ljava/lang/String; thrown while loading gnu.io.RXTXCommDriver
java.lang.NoClassDefFoundError: Could not initialize class gnu.io.RXTXCommDriver thrown while loading gnu.io.RXTXCommDriver

RXTX自体が古く、JDKのバージョンを追えていないので、configureファイルとconfigure.inファイルへ以下の変更を加える。


$ vi configure
case $JAVA_VERSION in
1.2*|1.3*|1.4*|1.5*)

1.2*|1.3*|1.4*|1.5*|1.6*|1.7*)
※上記の場所を以下へ変更する。
configureファイル :21544、21614、21750、21802行目
configure.iniファイル:466、536、672、724行目

makeの以下のエラーを排除する。


error: 'UTS_RELEASE' undeclared (first use in this function)

■OSのバージョンを取得


$ uname -r
3.0.6
■version.hを編集する。最終行に以下を追加する。

$ sudo vi /usr/include/linux/version.h
#define UTS_RELEASE "3.0.6"
再ビルドする。

$ make clean
$ ./configure
$ make
コピーして、起動して確認する。

$ sudo cp RXTXcomm.jar /usr/local/jdk1.7.0_21/jre/lib/ext/
$ sudo cp ./armv7l-unknown-linux-gnu/.libs/librxtxSerial-2.1-7.so /usr/local/jdk1.7.0_21/jre/lib/arm/
$ java Test
実行結果

Experimental: JNI_OnLoad called.
Stable Library
=========================================
Native lib Version = RXTX-2.1-7
Java lib Version = RXTX-2.1-7
/dev/ttyUSB0
/dev/ttyS1
/dev/ttyS0

動作確認のサンプルコード
Test.java


import gnu.io.CommPortIdentifier;
import java.util.Enumeration;

public class Test{
public static void main(String[] args){
System.out.println("main method start.");
try{
Enumeration portList = CommPortIdentifier.getPortIdentifiers();
CommPortIdentifier port = null;
while (portList.hasMoreElements()) {
port = (CommPortIdentifier)portList.nextElement();
System.out.println(port.getName());
}
}catch(Exception e){
e.printStackTrace();
}
}
}