code up

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Antでターゲットを継承する

Ant 1.8.2での話。

includeタスクというのとimportタスクという外部のbuild.xmlを取り込むタスクがある。違いを調べた。

Antのドキュメント

includeまたはimportでは、次のように記載されている。

How is <import> different from <include>?

The short version: Use import if you intend to override a target, otherwise use include.

When using import the imported targets are available by up to two names. Their "normal" name without any prefix and potentially with a prefixed name (the value of the as attribute or the imported project's name attribute, if any).

When using include the included targets are only available in the prefixed form.

When using import, the imported target's depends attribute remains unchanged, i.e. it uses "normal" names and allows you to override targets in the dependency list.

When using include, the included targets cannot be overridden and their depends attributes are rewritten so that prefixed names are used. This allows writers of the included file to control which target is invoked as part of the dependencies.

It is possible to include the same file more than once by using different prefixes, it is not possible to import the same file more than once.

簡単に訳すと、

importincludeの違いは?

一言で言うと、ターゲットを継承したいならばimportを使い、そうでなければincludeを使う。

importで読み込まれたターゲットは最大二つの名前を使って利用できるようになる。"通常の"名前であるプレフィックスなしのものと、プレフィックス付きの名前である(プレフィックスは、as属性で指定されたものかprojectタグのname属性)。

include時はincludeされたターゲットはプレフィックス付きでしか呼び出せない。

import時はimportされたターゲットのdepends属性はそのまま残る。つまり、"通常の"名前(プレフィックスなしの名前)を呼び出すので、依存(depends)しているターゲットを継承することが可能となる。

include時にはincludeされたターゲットの継承はできず、dependsに書かれたにはターゲットにはプレフィックスが付けられ、それが呼ばれる。これによりinclude用のファイルを書く人が、依存しているターゲットのどのターゲットを呼びだすかを制御することができる。

同じファイルを違うプレフィックスで2回以上includeすることが可能である。同じファイルを2回以上importすることはできない。

import/includeはそのターゲットの前とか後とか記述する位置がどこでも影響はない。target外(project直下)でしか読み込めない。読み込むと、

import only allowed as a top-level task

とトップレベルで書けよ、と怒られる。なぜかincludeしても同じエラーメッセージ。

as属性が指定されずにprojectタグのname属性の指定がどちらにもない場合、importはプレフィックス付きの呼び出しができなくなるだけでエラーにはならないが、includeでは次のエラーが出る。

can't include build file parent.xml, no as attribute has been given and the project tag doesn't specify a name attribute

また、projectタグのname属性がどちらも空文字("")だった場合、includeすると同じエラーとなり、importprojectタグのname属性が重複しているというエラーで失敗する。

Duplicated project name in import. Project defined first in \build.xml and again in \parent.xml

importあるいはincludeされたターゲットはant -projecthelp -debugとすることで確認することができる。

>ant -projecthelp -debug
(略)

Main targets:

 a                   a
Other targets:

 m.a
   depends on: m.b
 m.b
 m.c
 m.d
 m.x
   depends on: m.a
Default target: x

Main targetsはdescription属性で説明が書かれたターゲット。Other targetsはそうでないもの。

parent.xml

こんな感じのxmlを用意。ターゲットxが実行されると、b→a→d→x→cという順番で呼ばれる。

<?xml version="1.0" encoding="UTF-8"?>
<project name="parent" default="x" basedir=".">

	<target name="a" depends="b">
		<echo message="a 外部ファイル" />
		<antcall target="d" />
	</target>

	<target name="b">
		<echo message="b 外部ファイル" />
	</target>

	<target name="c">
		<echo message="c 外部ファイル" />
	</target>

	<target name="d">
		<echo message="d 外部ファイル" />
	</target>

	<target name="x" depends="a">
		<echo message="x 外部ファイル" />
		<antcall target="c" />
	</target>

</project>

build.xml - importで読み込む。

<?xml version="1.0" encoding="UTF-8"?>
<project name="child" default="x" basedir=".">

	<import file="parent.xml" as="m"/>

	<target name="a">
		<echo message="a 呼び出し元ファイル" />
	</target>

</project>

ターゲットxを実行。

>ant x
Buildfile: \build.xml
Trying to override old definition of datatype resources

a:
     [echo] a 呼び出し元ファイル

x:
     [echo] x 外部ファイル

c:
     [echo] c 外部ファイル

BUILD SUCCESSFUL
Total time: 0 seconds

ターゲットaだけ継承できている。importしたファイルで元々定義されていたターゲットaの処理、つまりターゲットbとターゲットdの呼び出しは上書きされた結果、実行されなくなった。

元々定義されていたparent.xmlにあるターゲットaを呼び出したい場合は、ant m.aとすればよい。

build.xml - includeで読み込む。

<?xml version="1.0" encoding="UTF-8"?>
<project name="child" default="x" basedir=".">

	<include file="parent.xml" as="m"/>

	<target name="a">
		<echo message="a 呼び出し元ファイル" />
	</target>

</project>

ターゲットm.xを実行。

>ant m.x
Buildfile: \build.xml
Trying to override old definition of datatype resources

m.b:
     [echo] b 外部ファイル

m.a:
     [echo] a 外部ファイル

BUILD FAILED
parent.xml:367: The following error occurred while executing this line:
Target "d" does not exist in the project "client".

Total time: 0 seconds

include時、depends属性に書かれたターゲットは自動的にプレフィックスが付いて呼ばれる(ターゲットm.bは実行された)がantcallで呼び出すターゲットはプレフィックスが付いてくれないのでエラーとなるので注意が必要。

Trying to override old definition of datatype resources

ふと見るとTrying to override old definition of datatype resourcesというメッセージが標準出力に出ている。

どうやらtaskdeforg.apache.catalina.ant.ResourcesTaskを取り込んでいるところで発生しているらしい。

<taskdef name="resources" classname="org.apache.catalina.ant.ResourcesTask" classpathref="ant.classpath" />

これは、resourcesというタグは既にAntの1.7以降で使われているタグだったためで、つまりこのタグを上書きしているために発生している警告メッセージであった。

従って元のresourcesタグを使うのであれば、そのtaskdefを削除するか、違う名前で定義し直す必要がある。

<taskdef name="catalina-resources" classname="org.apache.catalina.ant.ResourcesTask" classpathref="ant.classpath" />
関連記事
タグ:Java Ant
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。