JAVAでソフトウェアを開発する人が、Linux用のネイティヴなアプリケーションを書けるように、gcjの使いかたから紹介するものです。
ツールとしては、Apache ANT,SWT(Eclipse)を使用します。GUI toolkitとしては、AWTやSwingがJAVAの標準として提供されていますが、両方ともGCJではうまく動きません。そのため、SWTを使用することにしました。
全てのLinuxを対象にします。Slackware, Plamo, Debian, MIRACLE, RedHat, Novell SUSE, Mandrake, Turbo, Vine, Momonga など、システム、パッケージ形式を問わずに書きます。各ディストロ毎の違いは、他のサイトを参照してください。
JAVAが元になるので、MacOS X, FreeBSD, NetBSD, Solarisなどでも動かせるとは思いますが、敢えて触れることはないでしょう。
Linuxをインストールしていない、若しくはするつもりがない場合は、gccのクロスコンパイル機能を使うという手がありますが、いろんな意味でお薦めしません。Linuxはお金をかけずにコンピュータを使う、最良な方法のひとつです。
gcjをインストールするには、いくらかの方法が有ります。ソースからの場合、gcc.gnu.orgからダウンロードできますが、既にgccはあるでしょうから、バージョンアップ以外では考えることないでしょう。rpmの場合、rpmfind.netからgcc-javaをダウンロードしてください。debな場合、debian オフィシャルにあります(詳しくありません)。
JAVAを知らないと意味がありません。まずは、JAVAを学んでください。すべてはそこから始まります。
但し、既にC言語を知っている場合、無理にgcjを使う必要はありません。gccでプログラミングしてください。
基本的には、独自のやり方で通用するでしょう。しかし、技法を統一することで、他人のソースを改造したり、他人がソースを改造したりすることが容易になると信じます。そこで、方法のひとつを紹介します。
OOo calc,kivioなどを使って、必要な機能を箇条書きにします。UMLなどを使って図示します。
実際にプログラミングをしていくわけですが、見通しをよくするために、まず、基準のディレクトリから、クラスのパッケージ名にしたがって、ディレクトリを作り、空きのファイルを置きます。
それぞれのクラスにクラス宣言文とクラスの内容を示すコメントを書きます。
メソッド、フィールドの宣言を書き、その内容を示すコメントを書きます。
メソッドを実装します。
2まで完了しているとして、HalloWorldを考えます。
/**このクラスでは、標準出力にHallo Worldと出力します。**/
public class HalloWorld
{
}//HalloWorld
これが次の段階でこうなります。
/**このクラスでは、標準出力にHallo Worldと出力します。**/
public class HalloWorld
{
/**メインメソッドで、標準出力にHallo Worldと出力します。**/
public static void main(String[] args)
{
}//main
/**コンストラクタです。**/
public void HalloWorld()
{
}//HalloWorld
}//HalloWorld
これが次の段階でこうなります。
/**このクラスでは、標準出力にHallo Worldと出力します。**/
public class HalloWorld
{
/**メインメソッドで、標準出力にHallo Worldと出力します。**/
public static void main(String[] args)
{
String message = "Hallo World";
System.out.println(message);
}//main
/**コンストラクタです。**/
public void HalloWorld()
{
}//HalloWorld
}//HalloWorld
コンパイルするには、2つの方法があります。shared libraryにするか、実行可能形式にするか、です。どっちにしても書式はほとんど変わりません。
$ gcj [options] -o outputfile inputfile [inputfile...inputfileは複数書くことが出来ます。gcjなので、ファイル名は、~.javaという名前になるでしょう。
outputfileは好きな名前にできます。inputfileとして指定した全てがひとつのoutputfileになります。-oに続けて書きます。但し、shared libraryにした場合、lib + outputfile + .so というファイル名になります。
オプションは使いきれないくらいあるので、gcjガイド[www.asahi-net.or.jp]やgoogle[www.google.co.jp]あたりを参照してください。
shared libraryにしたい場合、単純にオプションに -shared をつけるだけです。
$ gcj -shared -o outputfile inputfile [inputfile...この場合、出力されるファイル名は liboutputfile.so です。
サンプルを示します。ファイル HalloWorldをコンパイルする場合です。
$ gcj -shared -o halloworld HalloWorld.javalibhalloworld.soができあがりますが、これの置く場所は、/usr/libか、/etc/ld/so.confに書かれている場所になります。そうしないと、このshared libraryをリンクした実行可能ファイルがlibhalloworld.soを見付けられず、実行できない羽目に遭います。
実行可能形式にしたい場合、オプションに --main をつけます。
$ gcj --main=mainclass -o outputfile inputfile [inputfile...この場合、inputfileのひとつ、mainclassがソース中に"public static void main(String[])"を含む必要があります。
サンプルを示します。ファイル HalloWorld,HalloWorld1,HalloWorld2,HalloWorld3の4つをひとつの実行形式ファイルにコンパイルする場合です。ここでは、HalloWorld3が"public static void main(String[])"を含み、パッケージ"mypackage.sample"に所属するものとします。
$ gcj --main=mypackage.sample.HalloWorld3 -o HalloWorld mypackage/sample/HalloWorld.java mypackage/sample/HalloWorld1.java mypackage/sample/HalloWorld2.java mypackage/sample/HalloWorld3.javamainとしてのHalloWorld3とinputfileとしてのHalloWorld3の指定方法の違いにも着目してください。
実際問題として、このままじゃ、毎回なっが〜い文を書くことになり、非効率的です。なんぼ、上↑キーや、historyコマンド、タブ補間ができたとしても。ほんで、makeやANTANTを使った方がいいんじゃないかと思います。いや、お薦めします。
Apache ANTとは、XMLベースのコンパイル補助で、主にJAVA用です。しかし、工夫すれば、何にでも応用できます。そして、ここでは、簡単にした説明を述べます。それをあなたがどう使うかはあなたの自由です。
ANTの導入は、rpm,deb,tarballのいずれかをインストールするだけです。普段やっているだろうから、ここの説明はありません。
JDKを先に導入する必要があります。これは、JAVA.comから導入してください。また、環境変数ANT_HOME,JAVA_HOME,PATHが正しく設定されている必要があります。JAVA_HOMEの設定と、PATHにjava,javacを含むディレクトリの追加については、別のsiteへ。
ANT_HOMEとして、antをインストールしたディレクトリを設定する必要があります。
ANTは、build.xmlに書かれた通りにコンパイルします。適当に(適切とも)build.xmlを書きさえすればいいのです。そうして、下記のように実行すれば、終了です。いくらかのオプションがありますが、-helpオプションつきで起動すればわかると思います。build.xmlこそが難関であって、起動方法は問題にならないでしょう。
$ ant -vまず、適当な(適切とは言い替えられない)サンプルを示しましょう。それにコメントしますので、それを以って使いかたを理解してください。
1 <?xml version="1.0"?>
2 <project name="sampleAWT sampler" default="main">
3 <description>
4 This build.xml is build a sampleAWT.
5 </description>
6 <property name="basedir" value="."/>
7 <property name="dstdir" value="../bin"/><!-- for javac -->
8 <property name="dstfile" value="../bin/sampleAWT"/><!-- for gcj -o -->
9 <property name="mainclass" value="nippon.tokyo.dreamtheater.test.sampleAWT"/>
10 <property name="srcdir" value="nippon/tokyo/dreamtheater/test/"/>
11 <property name="docdir" value="../doc/"/>
12 <property name="tarball" value="sampleAWT"/>
13 <property name="manifest" value="${dstdir}/nippon/tokyo/dreamtheater/MANIFEST/manifest.sampleAWT"/>
14 <property name="bindir" value="${dstdir}/${srcdir}"/>
15
16 <target name="main" description="compile with gcj">
17 <apply executable="gcj" dir="${basedir}" parallel="true">
18 <!-- output file is -->
19 <arg line="-o ${dstfile}"/>
20 <!-- mainclass is -->
21 <arg value="--main=${mainclass}"/>
22 <!-- source is -->
23 <fileset dir="${srcdir}" includes="*.java"/>
24 </apply>
25 </target>
26
27 <target name="javac" description="compile with jdk after make jar,javadoc">
28 <javac srcdir="${srcdir}" destdir="${dstdir}"/>
29 <antcall target="jar"/>
30 <antcall target="javadoc"/>
31 </target>
32
33 <target name="jar" description="make jar (Do not use. use only on javac task)">
34 <jar destfile="${dstdir}/${tarball}.jar" manifest="${manifest}" duplicate="preserve">
35 <zipfileset dir="${dstdir}/${srcdir}" prefix="${srcdir}" includes="*.class"/>
36 </jar>
37 </target>
38
39 <target name="javadoc" description="make jdk's javadoc package (Do not use. use only on javac task)">
40 <javadoc destdir="${docdir}" docencoding="UTF-8">
41 <fileset dir="${basedir}" includes="**/*.java"/>
42 </javadoc>
43 <exec executable="date" outputproperty="date">
44 <arg value="+%y%m%d%H%M"/>
45 </exec>
46 <tar destfile="${tarball}${date}.doc.tar.bz2" compression="bzip2">
47 <tarfileset dir="${docdir}"/>
48 </tar>
49 </target>
50
51 <target name="srcpack" description="make source package">
52 <exec executable="date" outputproperty="date">
53 <arg value="+%y%m%d%H%M"/>
54 </exec>
55 <echo message="${date}"/>
56 <tar destfile="${tarball}${date}.tar.bz2" compression="bzip2">
57 <tarfileset dir="${basedir}" includes="${srcdir}*.java"/>
58 </tar>
59 </target>
60
61 </project>
大幅にはしょって行きましょう。重複はしません。閉じタグについては、字下げをしているのでわかると思います。
1行目:XMLの宣言文です。ここにcharsetを指定しない場合、UTF-8で書かれたものだと判断されます。
2行目:build.xmlの宣言文といえる、projectタグです。nameには適当な名前を付ければいいでしょう。defaultには、オプション指定しなかった場合に実行する、ターゲットを記述します。
3行目〜5行目:projectタグの詳細情報です。ANTを-projecthelpで起動した時に表示されるものです。
6行目〜14行目:propertyタグです。変数を設定し、今後出てくるディレクトリやファイルをここで指定しておけば、将来ディレクトリやファイルの名前が変わった時に柔軟に対応できるようになるでしょう。この変数を使うには、13〜14行目にもあるように、${ }で変数名を括ります。
16行目:targetタグです。2行目で指定しているdefaultは、このタグの名前です。nameはなんでも構いません。descriptionは、3〜5行目と同じです。
17行目〜23行目:gcjでコンパイルする部分です。
17行目:applyタグは、ANTを実行するコンピュータが持っているプログラムを実行するものです。ここでは、gcjを実行しています。dirは、"どこで"を指定します。
19行目:argタグは、applyの引数を指定します。ここでは、gcjの-oオプションを指定しています。
21行目:上と同じです。ここでは、gcjの--mainオプションを指定しています。
23行目:filesetタグは、fileの塊を設定する物です。${srcdir]にある、.javaで終わるファイル全てが指定されています。
27行目〜31行目:gcjのコンパイルに失敗したときの為に、javacでコンパイルできるように書いています。
29行目〜30行目:antcallタグは、build.xml内のtargetタグを実行するものです。
33行目〜37行目:javacでコンパイルしたあと、jarでパッケージングするために書きました。
39行目〜49行目:javacでコンパイルしたあと、javadocを生成するためのものです。
51行目〜59行目:ソースをtarballに収めるためのものです。
52行目〜54行目:execタグは、applyタグと同様ですが、fileset(23行目)が不要な場合はこちらを指定します。ここでは、dateコマンドを実行し、変数dateにその結果を格納(outputproperty)しています。
55行目:標準出力にメッセージを出力します。ここでは、変数dateの内容を出力しています。
56行目〜58行目:tarタグで、tarballを作ります。ここでは、上の変数dateを入れることで、パッケージのバージョン管理を行っています。圧縮方式にbzip2を使用しています。
以上になりますが、(多分ほとんどの人がそうであろうが、)よくわからない場合は、ANT本を読むといいかも知れません。でもそれは決してLinuxや他のUnix系向けではないことに腹を立てられるかも知れませんし、gcjを使うにはどうするかってことがほとんど触れられていないことに、激昂するかも知れません。それとこれを並べて読むとよりよい解決策になれるであろうと信じています。