本頁面將說明建構系統的定義、功能、使用建構系統的原因,以及為何在組織開始擴大規模時,編譯器和建構指令碼並非最佳選擇。這項工具適用於不熟悉建構系統的開發人員。
什麼是建構系統?
從根本上來說,所有建構系統都有一個簡單明瞭的目的:將工程師編寫的原始碼轉換為可供機器讀取的可執行二進位檔。建構系統不只適用於人為編寫的程式碼,還能讓機器自動建立建構作業,無論是測試或發布正式版都一樣。在擁有數千名工程師的機構中,大多數的建構作業都是自動觸發,而非由工程師直接觸發。
我可以直接使用編譯器嗎?
您可能一時無法察覺需要建構系統。大多數工程師在學習編寫程式時不會使用建構系統:大多數人會直接從指令列呼叫 gcc
或 javac
等工具,或是在整合式開發環境 (IDE) 中呼叫等效工具。只要所有原始碼都在同一個目錄中,以下指令就能正常運作:
javac *.java
這會指示 Java 編譯器將目前目錄中的每個 Java 來源檔案轉換為二進位類別檔案。在最簡單的情況下 您只需要做到這點
不過,一旦程式碼擴充,就會開始出現複雜性。javac
夠聰明,可以查看目前目錄的子目錄,找出要匯入的程式碼。但它無法找出儲存在檔案系統其他部分的程式碼 (可能是多個專案共用的程式庫)。另外,它也只知道如何建構 Java 程式碼大型系統通常包含以各種程式設計語言編寫的不同部分,且這些部分之間有依附元件網絡,這表示沒有任何單一語言的編譯器可以建構整個系統。
一旦您開始處理多種語言或多個編譯單位的程式碼,建構程式碼就不再是單一步驟的程序。您現在必須評估程式碼的依附項目,並依正確順序建構這些部分,可能會為每個部分使用不同的工具組合。如果有任何依附元件變更,您必須重複執行這項程序,避免依賴過時的二進位檔。即使是規模適中的程式碼庫,這個程序也會很快變得乏味且容易出錯。
此外,編譯器也不知道如何處理外部依附元件,例如 Java 中的第三方 JAR
檔案。如果沒有建構系統,您可以透過下列方式管理這個問題:從網際網路下載依附元件、將其放在硬碟上的 lib
資料夾中,然後設定編譯器,讓其讀取該目錄中的程式庫。隨著時間過去,要維護這些外部依附元件的更新、版本和來源並不容易。
殼層指令碼呢?
假設您的興趣專案一開始很簡單,您可以只使用編譯器建構專案,但開始遇到先前所述的部分問題。也許您仍認為自己不需要建構系統,而且可以使用一些簡單的 Shell 指令碼,以正確順序建構項目,自動執行繁瑣的部分。這種做法有一段時間可執行 但很快就會開始遇到更多問題
這會變得乏味。隨著系統越來越複雜,您開始花費的時間,在建構指令碼上花費的時間幾乎與實際程式碼相同。因為有越來越多駭客會層層堆疊,因此殼層指令碼的偵錯作業相當耗時。
速度較慢。為確保您不會意外使用過時的程式庫,請在每次執行建構指令碼時依序建構每個依附元件。您考慮新增一些邏輯來偵測需要重建的部分,但這對指令碼來說似乎非常複雜且容易出錯。或者,您想指定每次需要重建哪些部分,但又回到原點。
好消息:現在是發布更新的最佳時機!建議您找出所有需要傳遞至 jar 指令的引數,以便進行最終建構作業。並記得如何上傳並推送至中央存放區。並建立及推送文件更新,以及傳送通知給使用者。嗯,也許這次的呼叫是另一個指令碼...
太慘了!您的硬碟當機,現在您需要重新建立整個系統。您很聰明,將所有來源檔案都保留在版本控制中,但下載的程式庫呢?你可以再次找到這些檔案,並確認這些檔案與你首次下載的版本相同嗎?你的指令碼可能會依賴在特定位置安裝特定工具,請問你能否還原相同環境,讓指令碼再次運作?您很久以前設定的所有環境變數,是否都會讓編譯器正常運作,但您卻忘記了?
儘管出現問題,但您的專案已成功聘僱更多工程師。您現在應該已經瞭解,前述問題並非災難,只是每次有新開發人員加入團隊時,您都必須經歷相同的啟動程序。即使您盡力調整,每個人的系統仍會有些微差異。在某人機器上運作的程式,往往無法在其他人機器上運作,而且每次都需要花上好幾個小時來偵錯工具路徑或程式庫版本,才能找出差異所在。
您決定需要自動化建構系統。理論上,這就像取得新電腦,並設定讓電腦每天晚上使用 cron 執行建構指令碼一樣簡單。您仍然需要完成痛苦的設定程序,但現在沒有人腦的好處,無法偵測和解決小問題。如今,每天早上上班時,您會發現昨晚的建構作業失敗,因為昨天開發人員所做的變更在他們的系統上可行,但在自動建構系統中卻無法運作。每次您只是一個簡單的修正方法,卻常常發生在每天花大量時間尋找並套用這些簡單的修正。
隨著專案規模擴大,建構作業的速度會越來越慢。某天,您在等待建構作業完成時,無意間瞥見同事的電腦閒置在桌上,他目前正在度假,您希望能善用這項閒置的運算資源。
您遇到了典型的規模問題。對一名開發人員在最多一週或兩週內處理將近數百行程式碼 (可能只具備剛進大學的初級開發人員) 而言,只需使用編譯器即可。指令碼可能會讓您更深入瞭解。不過,一旦需要協調多位開發人員和他們的機器,即使是完美的建構指令碼也不足以應付,因為很難考量這些機器之間的細微差異。此時,這個簡單的方法就會失效,您必須投資於實際的建構系統。