2013年2月10日日曜日

[Ant]C コンパイル

  • Windows の cygwin で gcc を使用する場合はパスの問題で cygwin の bash 上ではうまく動作しない。Windows 標準のコマンドプロンプトで gcc を実行する場合は cygwin/bin に gcc-3.exe というファイルがあるので gcc.exe という名前でコピーして gcc を実行できるようにしておく。
  • ANT Build Guide を参考に C++ のコンパイルができるよう Ant-Contrib を入手する。
  • Java SDK がない場合は Java SE Downloads から JDK をダウンロードする。
  • ant を使用するときに \Program Files\ 以下に tools.jar がないと言われる場合は、JDK をインストールしたディレクトリの lib 以下に tools.jar があるのでそれを指定のディレクトリにコピーしておく。
  • ダウンロードした ant-contrib の cpptasks で ant を実行し cpptasks.jar を作成する。cpptasks.jar は cpptasks-x.xx\target\lib に作成される。
  • cpptasks.jar を Ant の lib ディレクトリにコピーする。
  • cpptasks-x.xx\src\samples\hello で ant を実行しコンパイルできることを確認する。
  • ソースを作成するディレクトリ以下に src ディレクトリを作る。今回は ant_test というディレクトリで作成する。
    ant_test
        +--- src/
        |     +-- hello.c
              +--- build.xml
    
    Example: hello.c
    #include <stdio.h>
    int main(void)
    {
      printf("Hello, world\n");
      return 0;
    }
    
    Example: build.xml
    <?xml version="1.0"?>
    <project name="HelloWorld" basedir="." default="all">
      <taskdef resource="cpptasks.tasks"/>
      <property name="build.dir" value="build"/>
      <property name="dist.dir" value="dist"/>
      <property name="src.dir" value="src"/>
      <target name="init">
        <mkdir dir="${build.dir}"/>
        <mkdir dir="${dist.dir}"/>
      </target>
      <target name="clean">
        <delete dir="${build.dir}"/>
        <mkdir dir="${build.dir}"/>
        <delete dir="${dist.dir}"/>
        <mkdir dir="${dist.dir}"/>
      </target>
      <target name="compile" depends="init">
        <cc outtype="executable" subsystem="console" outfile="${dist.dir}/hello" objdir="${build.dir}">
          <fileset dir="${src.dir}" includes="*.c"/>
        </cc>
      </target>
      <target name="all" depends="init,clean,compile"/>
    </project>
    
  • コンパイラに cc を指定できるように次のように記述しておくことを忘れないようにする。
    <taskdef resource="cpptasks.tasks"/>
    
  • コンパイルは ant を実行すれば default で指定されている all が実行され、init, clean, compile が実行される。
  • dist, build などのディレクトリを作成しない場合は以下のように build.xml を記述できる。
    <?xml version="1.0"?>
    <project name="authAdminServiceStart" basedir="." default="all">
      <taskdef resource="cpptasks.tasks"/>
      <property name="obj.dir" value="."/>
      <property name="src.dir" value="."/>
      <target name="init">
      </target>
      <target name="clean">
        <delete>
          <fileset dir="." includes="*.o,*.exe"/>
        </delete>
      </target>
      <target name="compile" depends="init">
        <cc outtype="executable" subsystem="console" outfile="test" objdir="${obj.dir}">
          <fileset dir="${src.dir}" includes="*.cpp"/>
        </cc>
      </target>
      <target name="all" depends="init,compile"/>
    </project>
    

[Ant]Property

一度設定した property は上書きすることはできない
-v を付けて実行すると
Override ignored for property "HOGEHOGE"
と表示される

[Ant]SFTP

SFTP を使えるようにする
  1. JCraft から jsch-0.1.46.jar をダウンロードする
  2. ダウンロードしたファイルを ant インストールディレクトリにある lib に置く
  3. build.xml に以下を記載
    <target name="sftp-put">
      <scp todir="${FTPUSERID}:${FTPPASSWORD}@${FTPSERVER}:${FTPREMOTEDIRROOT}"
           file="test.txt"
           trust="true">
      </scp>
    </target>
    
  4. file 指定の代わりに fileset を使うことも可能
    <target name="sftp-put">
      <scp todir="${FTPUSERID}:${FTPPASSWORD}@${FTPSERVER}:${FTPREMOTEDIRROOT}"
           trust="true">
        <fileset dir=".">
          <include name="*.txt"/>
        </fileset>
      </scp>
    </target>
    

[Ant]build.xml 内で & 記号が使いたい

build.xml に上記の FTP 設定を書いている時にパスワードに & が使われていた
& は XML 記述内では予約語となっているので、そのまま書いたのでは build.xml を読み込ませたときにエラーが発生する
BUILD FAILED
home\build.xml:101: The entity name must immediately follow the '&' in the entity reference.
これは & を & と記述することで回避できる。
  • エラー
    password="pass&word"
    
  • OK
    password="pass&word"
    

[Ant]FTP

Fedora でのインストール方法
# yum install ant-commons-net
Windowsでのインストール方法
  1. FTP を使えるようにするため Apache Commons から Comons Net をインストールする
  2. 展開したファイルにある commons-net-3.1.jar を apache-ant をインストールしたディレクトリの lib に置く
  3. Windows Firewall が有効になっているので以下のように IO error が出る
    ftp-put:
    [ftp] sending files
    [ftp] try #1: IO error (index.html), number of maximum retries reached (0), giving up
    
動作確認
  1. build.xml に以下を記述して動作確認
    <target name="ftp">
      <ftp server="server 名"
           userid="ユーザ名"
           password="パスワード"
           action="list"
           listing="./ftplist.txt"
           remotedir="/">
        <fileset>
          <include name="*" />
        </fileset>
      </ftp>
    </target>
    
  2. build.xml を実行したディレクトリに ftplist.txt が作成される。中には以下のようなファイルリストが入っている
    -rw-r--r-- 1 11111 11111 4877 Aug 06 08:29 index.html
    
  3. サーバにファイルをアップロードする場合 (put)
    <target name="ftp-put">
      <ftp server="${FTPSERVER}"
           userid="${FTPUSERID}"
           password="${FTPPASSWORD}"
           action="put"
           remotedir="/">
        <fileset dir=".">
          <include name="*.html" />
        </fileset>
      </ftp>
    </target>
    

[Ant]Copy

ファイルを指定のディレクトリにコピーする
<copy file="test.txt" todir="${BUILD}"/>
実行結果
[copy] Copying 1 file to /home/username/build

[Ant]Ant が実行しているコマンドを確認する

ant を実行する時に -verbose オプションを付加することで実行しているコマンドを確認することができる。
>ant -verbose
Apache Ant version 1.7.1 compiled on June 27 2008
Buildfile: build.xml
Detected Java version: 1.6 in: C:\Program Files\Java\jdk1.6.0_13\jre
Detected OS: Windows XP
parsing buildfile C:\home\Ant_CppUnit\build.xml with URI = file:/C:/home/Ant_CppUnit/build.xml
Project base dir set to: C:\home\Ant_CppUnit
[antlib:org.apache.tools.ant] Could not load definitions from resource org/apache/tools/ant/antlib.xml. It could not be found.
Build sequence for target(s) `all' is [init, clean, compile, all]
Complete build sequence is [init, clean, compile, all, compileonly, linkonly, test, ]
init:
[mkdir] Skipping C:\home\Ant_CppUnit\build because it already exists.
[mkdir] Skipping C:\home\Ant_CppUnit\dist because it already exists.
clean:
[delete] Deleting directory C:\home\Ant_CppUnit\build
[delete] Deleting C:\home\Ant_CppUnit\build\Counter.o
[delete] Deleting C:\home\Ant_CppUnit\build\CounterTest.o
[Delete] Deleting C:\home\Ant_CppUnit\build\history.xml
[delete] Deleting C:\home\Ant_CppUnit\build\test.o
[delete] Deleting directory C:\home\Ant_CppUnit\build
[mkdir] Created dir: C:\home\Ant_CppUnit\build
[delete] Deleting directory C:\home\Ant_CppUnit\dist
[delete] Deleting C:\home\Ant_CppUnit\dist\history.xml
[delete] Deleting directory C:\home\Ant_CppUnit\dist
[mkdir] Created dir: C:\home\Ant_CppUnit\dist
compile:
[cc] 3 total files to be compiled.
[cc] g++ -c -g C:\home\Ant_CppUnit\src\test.cpp C:\home\Ant_CppUnit\src\CounterTest.cpp C:\home\Ant_CppUnit\src\Counter.cpp
[cc] Starting link
[cc] gcc -g -o test ..\build\test.o ..\build\CounterTest.o ..\build\Counter.o
C++ のソースを Ant でコンパイルを行おうとしていてもリンクエラーが発生することがある。その場合に -verbose オプションを付けて実行すると最後の行で gcc によりリンクを行おうとしていることが確認できる。
これにより手元の cygwin 環境には libstdc++ がインストールされていないことが判明したので、libstdc++ をインストール。
build.xml の該当箇所を以下のように修正し再度実行したところ無事にコンパイル・リンクを行うことができた。
<target name="compile" depends="init">
  <cc outtype="executable"
      subsystem="console"
      outfile="${dist.dir}/test"
      objdir="${build.dir}"
      debug="true">
    <compiler name="g++">
      <fileset dir="${src.dir}" includes="*.cpp"/>
    </compiler>
    <linker name="gcc" libtool="true">
      <libset libs="cppunit,stdc++"/>
    </linker>
  </cc>
</target>