注意我正在使用ant 1.7。通過Ant 1.8中的本地範圍,還有一些其他選項,以便不變性不是一個很大的挑戰,但其中一些其他技巧仍然有幫助。
首先,關於根據宏中的uptodate結果選擇執行任務的問題 - 這意味着您不需要2個目標。 爲此,請使用條件標籤。如果第一個條件失敗,<或>標記將使其僅執行第二個條件。 <scriptcondition>標籤允許使用JavaScript執行其他螞蟻任務。下面是一個例子(@標籤表示macrodef屬性):
<condition property="whatever" value="false">
<or>
<uptodate>
<srcfiles dir="@{srcdir}" includes="@{srcincludes}" excludes="@{srcexcludes}"/>
<mapper><chainedmapper>
<flattenmapper/><!-- use any mappers you need to match source to target files-->
<globmapper from="*.jxw" to="@{targetdir}\*W.java"/>
</chainedmapper></mapper>
</uptodate>
<!-- w/ java 1.6 or later, you get a rhino javascript interpreter included w/ java-->
<scriptcondition language="javascript" value="true">
self.setValue(true);
echo = project.createTask("echo");
myArg1="@{myArg1}";
myArg2="@{myArg2}";
// need to create a reference from a classpath refid
myReference = new org.apache.tools.ant.types.Reference(project,"@{my.classpath.id.string}");
// get a handle to the ant java task, which we will use to execute a java program
javaTask = project.createTask("java");
javaTask.setFork(true);
javaTask.setFailonerror(true);
javaTask.setClassname("com.mycompany.mypackage.MySpecialClass");
javaTask.setClasspathRef(myReference);
javaTask.createArg().setValue(myArg1);
javaTask.createArg().setValue(myArg2);
//output the command line to standard out, for reference
echo.setMessage(javaTask.getCommandLine());
echo.perform();
javaTask.perform();
</scriptcondition>
</or>
</condition>
現在,如果你像我一樣,你可能需要做一些處理與是你macrodef投入和產生可以參考一些派生值的屬性在你的macrodef腳本中。如果您正在處理的是簡單涉及屬性和字符串的連接,那麼您可以在塊中這樣做,如果您指定了屬性,則應指定第二組屬性,並使用包含連接步驟的默認設置。但是,如果您需要執行某些不能插入屬性默認值的操作,則需要將其放入屬性中。因爲屬性是不可變的,所以你需要採取一些額外的步驟來給你的屬性賦予唯一的名字。 tstamp派上用場,幫助解決這個問題。通常,傳遞給您的宏的參數的某些組合將是唯一的,但是如果這種獨特的組合包含反斜槓,則需要使用tstamp標籤派生次要唯一標識符,以便在JavaScript中不會遇到反斜槓問題你想使用這些派生屬性。以下是如何創建您可以在腳本中輕鬆引用的獨特屬性。
<macrodef name="public.macro.example">
<attribute name="srcpath"/>
<sequential>
<tstamp prefix="@{srcpath}"><format pattern="ddhhmmssSSS" property="time"/></tstamp>
<private.macro.example srcpath="@{srcpath}" propertyPrefix="prop${@{srcpath}.time}"/>
</sequential>
</macrodef>
<macrodef name="private.macro.example">
<attribute name="srcpath"/>
<attribute name="prefix"/>
<sequential>
<pathconvert property="@{prefix}.src"/>
<!-- now you can do special things with ${@{prefix}.src}, even in javascript -->
<script language="javascript">
self.setValue(true);
echo = project.createTask("echo");
myPrefix="@{prefix}";
mySpecialPropertyKey=myPrefix+".src";
//if your special property contains backslashes or other special js characters
// you need to use project.getProperty instead of a string literal to get the value
mySpecialPropertyVal=project.getProperty(mySpecialPropertyKey);
// do something with this derived value in javascript
echo.setMessage("my special property = "+mySpecialPropertyVal);
echo.perform();
</script>
</sequential>
</macrodef>
我想出了上面的解決方案之前,我想出了溶液用新值覆蓋螞蟻財產黑客攻擊的風格。雖然您可能會發現這適用於覆蓋屬性,因爲我正在直接調用ant類,但在未來的ant版本中可能不會有相同的風險。因爲這看起來更像是一種黑客行爲,所以我的意圖是儘可能使用上面列出的macrodef方法,而不是這種方法。請注意,此特定變體不支持反斜槓字符,因爲這些屬性是直接在JavaScript字符串文字中引用的。我最初使用這個簡單的變體來創建我獨特的前綴,這就避免了需要採用兩個macrodef方法來解決財產不可變性問題。然而,您可以使用project.getProperty命令來調整此宏定義以使用第二個macrodef和唯一前綴以將「@ {value}」賦值給JavaScript。
<macrodef name="public.canova.setproperty">
<attribute name="name"/>
<attribute name="value"/>
<sequential>
<script language="javascript">
project.setUserProperty("@{name}","@{value}");
</script>
<sequential>
</macrodef>
乍一看,一些本可能看起來有點複雜,但如果你做你macrodef工作的權利,並建立組件風格的宏(即不要把麪條代碼在宏),您的Ant腳本應實際上變得更短,更容易理解並且更容易維護,並且日誌將更容易遵循。提示 - 只有在必要時才使用javascript,當您使用它時,最好在宏內使用它,以便將其封裝並遠離螞蟻腳本的主要「邏輯」,從而有助於自我記錄和可讀性你的主要'邏輯'。當事情不明顯時使用註釋。
這種技術的一個問題。 @ {value}在腳本中作爲字符串文字內聯。因此,如果值包含反斜槓或雙引號,則結果不符合預期。 – gawi 2010-10-04 18:45:34
我知道這是一箇舊帖子,但至於您的請求,包括該電子郵件地址,請參閱[其他人可以編輯我的帖子?!](http://stackoverflow.com/faq#editing)(我是肯定會發生)和[如何使用代碼來處理海報需要的代碼?](http://meta.stackexchange.com/questions/117084/how-to-handle-answer-where-poster-wants-credit - 用於碼-如果使用的) – Arjan 2011-12-25 00:26:29