2011-05-12 58 views
6

承認,這聽起來不像是一個最佳實踐,但讓我解釋一下。在構建過程中,我們需要將內部版本號和系統版本粘貼到一個類中,其唯一目的是包含這些值並使其可訪問。螞蟻搭建期間修改代碼的最佳做法

我們的第一個想法是使用系統屬性,但由於部署環境的不穩定(另一種說法是「系統管理員正在做怪異的令人毛骨悚然的事情」),我們希望將它們硬編碼。

基本上我看到4種可能性,以實現它的螞蟻:

  1. 使用<replace>令牌上的類

    這種方法的問題是,該文件被改變了,所以你必須在編譯後使用<replaceregexp> ... sooo醜,我不想用正則表達式觸摸源代碼。加上時間依賴性。

  2. 副本的文件,使更換副本,編譯複製,刪除複製

    一個人有想到序列 - 原班是爲了通過拷貝覆蓋到先編譯。時間依賴性也很糟糕。

  3. 複製文件,替換原來的令牌,編譯,使用複製

    相同的時間相關性問題取代原來的染色,除非嵌入在編譯目標。這也是醜陋的,因爲我們所有的構建文件都使用相同的導入編譯目標。

  4. 在構建腳本/存儲從頭開始創建該文件的源路徑

    外的文件是比前三的改善,因爲沒有時間上的依賴關係,但是編譯器/ IDE很不爽因爲它沒有注意到課堂。紅色標記令人不安。

對替代品有什麼看法?

有沒有這方面的最佳做法?

我當然希望我錯過了一個完全理智的方法。

謝謝

編輯 我們結束了使用清單存儲在Implementation-Version屬性的版本號和系統版本,unsing MyClass.class.getPackage().getImplementationVersion()。我發現這個解決方案是this thread的答案之一,它被髮布在andersoj的評論中

+0

相關的我的一個問題:http://stackoverflow.com/questions/690419/build-and-version-numbering-for-java-projects-ant-cvs-hudson – andersoj 2011-05-12 17:11:50

+0

@andersoj:很好的資源,謝謝 – kostja 2011-05-12 17:21:00

回答

10

我認爲一個更簡單的方法是讓你的Version.java類從包含在JAR中的簡單的.properties文件中讀取,並且只需在構建時在Ant構建中生成此.properties文件即可。例如,只需生成:

build.number = 142 
build.timestamp = 5/12/2011 12:31 

built-in <buildnumber> task in Ant已經完成了一半(參見第二個示例)。

+1

同意,另一個好處是瀏覽你的應用程序的jar文件,一個人可以看到它是什麼編號。事實上,你可能想考慮把這些東西放在jar的清單中。 – MeBigFatGuy 2011-05-12 16:31:48

+0

聽起來不錯,非常有意義。我想通過嘗試修改源代碼本身就是錯誤的。 – kostja 2011-05-12 16:33:29

+1

Ant提供了將信息放入清單的「清單」任務 - 而Java提供了一個可以獲取信息的Manifest類。 – 2011-05-12 19:44:38

0

我記得我們以一種不同的方式使用了第四種方法。在創建發行版時,您可以將發行版號傳遞給ant腳本.Ant腳本應該在發行版(config/properties文件)中包含該腳本,並且您的類應從中讀取它,可能會使用屬性文件或配置文件。

+0

像馬特b說的,還是我錯過了? – kostja 2011-05-12 16:36:06

+0

哦,我認爲我們都幾乎同時發佈 – sudmong 2011-05-12 16:52:59

1

我的解決辦法是:

  1. 使用在A級令牌:

    <replace dir="${source.dir}" includes="**/BuildInfo.*" summary="yes"> 
        <replacefilter token="{{BUILD}}" value="${build}" /> 
        <replacefilter token="{{BUILDDATE}}" value="${builddate}" /> 
    </replace> 
    

這種替換應該只發生在由執行構建步驟你構建系統,而不是在IDE內的編譯/調試會話中。

構建系統設置不應將更改的源代碼提交回源存儲庫,因此使用此方法不存在更改代碼的問題。

根據我的經驗,當您將構建信息放置在屬性文件中時無助於解,因爲管理員在升級時傾向於保留屬性文件 - 替換安裝中出現的屬性文件。 (構建屬性文件中的信息對我們是信息性的,它提供了在啓動時檢查屬性文件是否與代碼版本同步的機會。)

+0

「構建系統設置不應該將已更改的源代碼提交回源存儲庫......」。任何設計良好的構建系統都應該堅持這一點。 +1更改只能朝一個方向進行,清理時只需刪除構建目標和中間構建構件(如生成的源)。 – Dev 2011-05-12 17:05:30

+0

謝謝你,這種方法的問題(是我們的第一槍)是,這個課程要麼保持改變,並通過VCS顯示,並且不止一次使用已經替換的令牌進行簽入...因此,是一種回滾,或者像1中的,或者像3中的複製開關,帶有所有產生的問題 – kostja 2011-05-12 17:13:52

+0

考慮到我們的CI構建 - 檢出,修改,構建,刪除,你是對的。 ..令牌替換完美。但是我們希望能夠在我們的開發機器上生成與版本相同的版本 – kostja 2011-05-12 17:18:51

2

#2通常是我看到它完成的方式,除非您的未準備好編譯源應與您準備編譯源文件位於不同的位置。這樣可以避免時間問題,因爲它應該只編譯一次。

這是一個在軟件構建過程中始終顯示的常見模式。

模式是: 從某個資源生成源代碼然後編譯它。

這適用於很多東西從過濾編譯之前源生成RMI,CORBA,Web服務等接口存根...

複製源到指定的「生成的源的位置和做標記替換複製文件以生成源代碼,然後將生成的源代碼編譯到您編譯的類目標。

編譯順序取決於您的其他源是否依賴於生成的源。

+0

謝謝你的詳細解答。這聽起來像一個乾淨和理智的解決方案。 +1 – kostja 2011-05-12 17:07:50

0

我總是建議創建某種目錄並將所有內置代碼放在那裏。不要觸摸您簽出的目錄。我通常會創建一個target目錄,並將所有修改和構建的文件放在那裏。

如果沒有太多* .java文件(或* .cpp文件),請將它們複製到target/source' and compile there. You can use thetask with a`,以便在複製時使用內部版本號修改此文件的一個文件。

<javac srcdir="${target.dir}/source" 
    destdir="${target.dir}/classes" 
    [yadda, yadda, yadda] 
</java> 

這樣,你正在做任何修改在簽出源目錄,所以沒有人會意外地更改來檢查。另外,您可以通過簡單地刪除target目錄來執行清理

如果有成千上萬,如果不是數百萬的*.java文件,那麼你就可以在模板複製到target/source,然後編譯在這兩個{$basedir}/sourcetarget/source源。這樣,你仍然沒有掏出檢出的代碼,並留下一個機會,有人會意外檢查修改後的版本。而且,您仍然可以通過簡單地刪除target來執行clean

0

我正在尋找解決同一問題的方法,請閱讀以下鏈接:http://ant.apache.org/manual/Tasks/propertyfile.html我能找到解決方案。

我與NetBeans工作,所以我只需要這一塊的代碼添加到我的build.xml

<target name="-post-init"> 
    <property name="header" value="##Generated file - do not modify!"/> 
     <propertyfile file="${src.dir}/version.prop" comment="${header}"> 
      <entry key="product.build.major" type="int" value="1" /> 
      <entry key="product.build.minor" type="int" default="0" operation="+" /> 
      <entry key="product.build.date" type="date" value="now" /> 
    </propertyfile> 
</target> 

這每一次喲編譯乾淨的項目,並建立將增加次要版本。因此,只要小版本保持不變,您就可以保存以運行項目。

我只需要在運行系統中讀取文件。我希望這個幫助。