2010-03-05 29 views
1

我要發佈一個問題,我已經看到其他地方的變體,但是我沒有看到我提出的答案。我會隨後發佈我的答案。ANT。覆蓋屬性。在單個目標中的可選執行

爲了使用宏模塊化我的構建腳本,我想在同一個宏中同時包含updatetask和我想執行的任務(如果它不是最新的)。
如何做到這一點 - 使用腳本標記是好的 - 如果唯一傳入的唯一屬性是包含反斜槓的路徑,並且我需要在不同的調用中將不同的值傳遞給腳本標記。我需要避免涉及反斜槓時可能發生的任何字符串文字問題。使用獨特的屬性,我需要解決ant不變屬性行爲,並解決通常使用2個目標來處理最新處理決策的螞蟻模式,並需要解決字符串文字中反斜槓的JavaScript處理問題。

回答

2

注意我正在使用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,當您使用它時,最好在宏內使用它,以便將其封裝並遠離螞蟻腳本的主要「邏輯」,從而有助於自我記錄和可讀性你的主要'邏輯'。當事情不明顯時使用註釋。

+0

這種技術的一個問題。 @ {value}在腳本中作爲字符串文字內聯。因此,如果值包含反斜槓或雙引號,則結果不符合預期。 – gawi 2010-10-04 18:45:34

+7

我知道這是一箇舊帖子,但至於您的請求,包括該電子郵件地址,請參閱[其他人可以編輯我的帖子?!](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