Solution Guide for Migrating UNIX Build Environments

第 1 章 - 簡介

將軟體應用程式從 UNIX 移植至 Windows 眾多層面的事項,包括作業系統依存性、方法、安全性及小組架構,早已見諸於許多過往的文件中。這些需求,是軟體遷移專案過程中必須加以解決的問題。然而,在以往的文件中,卻極少提及一個應用程式遷移常見的層面:軟體建構環境 (software construction environment),有時候稱為建置程序 (build process) 或建置系統 (build system)。

軟體建構環境可能相當複雜,如果沒有規劃遷移軟體建構環境的方式,應用程式的遷移專案就可能不盡完善。本章會簡介 UNIX 和 Windows 中的軟體建構方法及程序、UNIX 與 Windows 之間的差異、以及如何將建置環境遷移至 Windows。

本页内容

軟體建構的問題
傳統 UNIX 建置程序
傳統 Windows 建置建構程序
遷移建置系統的策略

軟體建構的問題

軟體建構是指將原始程式碼轉換成可以傳遞的格式 (通常包括一或多個執行檔) 的程序。這個過程中可能包含任何數量的步驟。例如,在 C 語言的程式設計中,通常會將 C 原始程式檔 (hello.c) 及標頭檔 (hello.h) 轉換成目的檔 (hello.o),然後連結至程式庫 (libc.a) 中的模組,並且轉換成執行檔 (UNIX 上的 hello 檔案;Windows 上的 hello.exe 檔案)。在這一連串過程中可能還有其他步驟:也許必須先處理原始程式檔,之後才能進行編譯;也許必須在目錄之間移動目的檔,才能連結至正確的程式庫;也許必須將完成的執行檔重新命名、壓縮、刪除符號資訊、封存或內嵌在安裝程式封裝中。

很明顯的一點是,變更任何主要原始程式檔,就會變更最終的產品,即使所做的變更非常細微 (例如只是校正對話方塊中的拼字錯誤) 時亦然。就某種意義來說,最終產品是原始程式檔的具體呈現,而且最終產品是以原始程式檔為根基。

在轉換順序中,hello 檔案來自於 (依存於) hello.o 檔案及 libc.a 檔案;ile; the hello.o 檔案來自於 (依存於) hello.c 檔案及 hello.h 檔案。如果變更 libc.a,則會影響 hello 執行檔。 如果變更 hello.h,則會影響 hello.o,且因此會影響 hello 執行檔。

圖 1.1 中描繪出類似的一組依存關係。應用程式依存於三個檔案:libc.a、app.o 和 libgd.a。app.o 檔案依存於 app.c 和 app.h。如果 app.c 有變更,則必須重新產生 app.o 檔案並且連結至 libc.a 和 libgd.a,才能產生新版的應用程式。然而,如果 app.h 有變更,則幾乎所有中繼檔案都必須重新產生,才能確保所產生的應用程式和原始程式檔是同步的。

圖 1.1 簡單的軟體依存關係
圖 1.1 簡單的軟體依存關係

顯而易見的是,我們在此假設無論何時可以重現軟體建置 — 也就是說,一組既定原始程式檔及一組已知的轉換集必定會產生相同的產品。由此推演的結果,是如果原始程式檔有所變更,則產品也會隨之變更而必須再次產生。必須再次將轉換套用至原始程式檔及中繼檔案,才能確保目前的產品確實是目前的原始程式檔應該產生的產品。

然而,圖中還呈現出編譯器 (Compiler)、封存器 (Archiver) 及連結器 (Linker) 所套用的轉換,必須依賴環境以及命令指令碼檔案或設定檔。環境非常重要,因為存在的環境變數會覆寫其他地方的設定值,環境變數中也可能會含有重要的資訊。於是,在不同環境下作業的不同使用者,可以使用相同檔案來執行相同的命令,而所得的結果卻不盡相同。

大部分工具都允許透過其他機制來提供控制資訊,但是,除非在某處記錄了這項資訊及其他機制,否則是無法重現建置的。目前,任何的軟體技術都無法保證可以記錄所有資訊;唯一共同認知的禁令是,除非有記錄環境資訊、或是在屬於建置系統一部分的檔案中有明確設定環境資訊,否則不要使用環境資訊。然而,單獨遵循這一條禁令並不是保護建置環境的有效方式。

如果原始程式檔與最終產品之間無法同步,業務就會連帶受到影響。例如,公司員工會花費許多時間嘗試追蹤已經修復的停機問題,或是員工使用的產品版本不符合原始程式碼,因而無法追蹤最新發生的停機問題。

對於中型或大型的原始程式檔集合而言,可能的關係數量會快速增加。如果要保存所變更的檔案、變更是否會影響最終產品、以及必須重新產生的產品部分等記錄,這項工作的規模會龐大到令人望之卻步。軟體建置系統會自動化記錄的工作。記錄的資訊包括原始程式檔清單、最終產品、中繼形式以及執行轉換使用的命令等。

幾乎所有的軟體建置系統都會使用檔案時間戳記 (上次變更的時間) 來推斷是否有變更的檔案;如果 hello.o 依存於 hello.c,而 hello.c 的日期比 hello.o 的日期更遲,就會假設 hello.o 已經過期且必須重新產生。大部分的解決方案都會將欠缺的檔案視為過期;如果 hello 執行檔不存在,即使 hello.c 的日期比 hello.o 的日期更早,仍然必須重新產生 hello 執行檔。(在本範例中,因為 hello.o 與 hello.c 之間是可以接受的關係,所以建置系統應完成的步驟僅僅將 hello.o 轉換成 hello 檔案;假設已使用這個版本的 hello.c 來建立 hello.o)。

UNIX 和 Windows 都已經開發出多種方法,可以解決傳統的軟體建構問題。這些方法在下列各節中有概要敘述。這些是 UNIX 和 Windows 的軟體建構原始方法,任何的遷移作業都必須將這些方法納入考量。

傳統 UNIX 建置程序

UNIX 軟體建構的核心基礎,是稱為 make 的公用程式。目前,有一整組類似於 make 應用程式的系列,但是這些都是繼承自 Stu Feldman 於 1970 年代撰寫的 make 程式 (Feldman 1979)。make 程式是用於維護檔案集合間同步的檔案管理公用程式。make 公用程式會依據檔案的時間戳記來持續追蹤檔案之間的依存關係。通常會使用 make 公用程式來更新衍生自其他檔案的檔案;例如,可以使用 make 公用程式來更新衍生自相對應原始程式檔的目的檔,或更新衍生自目的檔的執行檔。

描述檔中指定檔案之間的關係 (依存性)。這個描述檔通常命名為 makefile 或 Makefile,並且廣泛稱為 makefile。

何謂 Makefile?

makefile 是含有規則清單的文字檔,通常具有三個部分:目標、依存性清單以及一或多個命令的集合。命令集合有時候稱為配方 (recipe)。make 的用途是執行必要命令,以確保維持最新的指定目標。

下列是使用 hello.c 來建置 hello.exe 的簡單規則。

hello.exe: hello.c hello.h
cc -o hello.exe hello.c

這項規則的目標、依存性及配方如下所示:

  • 目標。目標是所要產生的檔案名稱。 在這個範例中,目標是檔案 hello.exe。 如果目標的修改日期早於任何依存檔案的修改日期,或如果目標的不存在,目標就會被視為過期 (與最新相反)。如果判定目標已經過期,則會執行配方中的命令。

  • 依存性。依存性 (有時候稱為先決條件) 是檔案名稱清單。在這個範例中,依存性包括檔案名稱 hello.c 和 hello.h。如果這個檔案中任何檔案的修改日期比目標檔案更遲,則會將目標檔案視為過期,make 還會將依存性視為目標,並且遞迴地確保這些檔案是最新的。

  • 配方。當目標的日期相對於任何依存性過期時,就會執行配方中的命令清單。在這個範例中,配方是編譯命令 cc -o hello.exe hello.c。

不同版本的 make 公用程式可能包含其他功能,這與版本相關。依據檔案名稱來指定預設配方所使用的巨集功能和機制是常用的功能和機制,但卻不通用。這些機制已廣泛運用且相當好用,但是在不同版本 make 之間遷移 makefile 過程中卻會引發問題。

Make 如何運作

make 公用程式以兩階段來處理 makefile。在第一階段,會發出命令 make,促使 make 程式讀取並剖析檔案中第一目標的 makefile,這是預設目標。如果已在命令列上指定另一個目標,則 make 會使用指定的目標,而不會使用預設目標。在剖析 makefile 後,make 會組合一份依存性圖表。

在第二階段,make 檢查目標的時間戳記,並且比較視為依存性的檔案的時間戳記。如果任何依存檔案比目標更新,則 make 會叫用 Shell 來執行配方。一次僅建置一個目標。

makefile 處理比這個簡單範例更加複雜。例如,某些配方會使用 make 本身當做遞迴執行的命令。就另一個複雜的範例而論,可以執行推斷規則,以配對特定檔案類型轉換 (.c 轉 .o 或 .l 轉 .c) 與特殊配方。

如需深入瞭解 make 的運作方式,請參閱《使用 make 來管理專案》(英文) (1991 年 Oram 與 Talbott 合著)。

傳統 Windows 建置建構程序

Windows 開發人員使用 Integrated Developer Environment (IDE) 來撰寫、建構及偵錯軟體。IDE 通常提供下列功能:

  • 程式設計所需的所有開發工具,包括產生完整應用程式所需的編譯器、連結器以及專案/設定檔。

  • 檔案管理功能,適用於專案中所包含的原始程式檔、標頭檔、文件及其他資料。

  • 「所見即所得」(WYSIWYG) 編輯器,所提供的工具可以建立具有內建對話方塊及資源編輯器的使用者介面。

  • 應用程式偵錯。

  • 包含開發所需的任何其他程式之功能,將程式加入 [工具] 功能表即可達成。

Microsoft® Visual Studio® 是包含這個清單中所描述之所有函式及功能的 IDE,包括一組完整的開發工具集,適用於使用 Microsoft Visual Basic®、Microsoft Visual C++®、Microsoft Visual J++® 和 Microsoft Visual FoxPro® 等程式設計語言來建置可重複使用的應用程式。

就本質而言,Visual Studio 會執行 make 所執行的功能:包括儲存檔案、依存性及配方等清單;維護依存性圖表;以及當提供建置軟體的命令時,會針對比所屬目標更新的檔案來執行正確的配方。

除了這些基本功能以外,其他功能皆不同。不同處在於 make 是一種命令列工具;而 Visual Studio 是一種整合式開發環境。make 儲存資訊並且在稱為 makefile 的文字檔中明確描述依存性;Visual Studio IDE 使用方案容器及專案容器,而且其在檔案中儲存所有資訊的方式不如 make 所採用的文字檔方法明確。

Visual Studio .Net 運用方案容器及專案容器的概念。方案容器係由一或多個專案所組成,並且每個專案都是由一或多個項目所組成。項目可能是檔案或專案的其他部分,例如,參考、資料連線或資料夾。IDE 中包括方案總管,這是用於檢視及管理這些容器及相關項目的介面。

您可以運用這些容器,按下列方式來利用整合式開發環境:

  • 管理方案的整個設定或個別專案的設定。

  • 使用方案總管來處理檔案管理的詳細資訊,讓您專心處理開發作業中的各個項目。

  • 將有用的項目加入方案中的多個專案,或加入方案中,而不需要參考每個專案中的項目。

  • 處理與方案或專案無關的其他檔案。

本手冊並未提供詳盡的 Visual Studio IDE 資源。若要使用此 IDE 來遷移或重新撰寫軟體建構程序,您必須進一步研究 Visual Studio 產品,請參閱 Microsoft 網站提供的資訊並且查閱產品相關手冊。

遷移建置系統的策略

從 UNIX 遷移至 Windows 時,永遠至少有兩個可能的遷移策略。當您遷移應用程式時,或當遷移建置系統時,就可以運用這些策略。適用於建置系統的兩種可能遷移策略如下:

  • 使用 Windows 工具 (例如 Visual Studio 中內建的功能),在 Windows 上重新建立建置系統。

  • 運用 Windows 上的 UNIX 可攜性環境,儘可能遷移現有的 makefile。

這兩項遷移策略各有優缺點。下列清單列出了這些優缺點:

  • 重新建立策略的優點。因為建置系統包含的檔案比應用程式包含的檔案少,所以系統通常會採用重新建立策略。重新建立策略不需要嘗試兩種環境之間的對應,因而有時候重新建立策略比遷移策略更加便利。由於 Windows 工具會持續進展,所以 Visual Studio 架構建置系統也較容易維護。

  • 重新建立策略的缺點。雖然重新建立策略有一些優點,您仍然必須瞭解現有建置程序的運作方式,才能重新建立新的建置程序,並且必須訓練您的開發人員使用新的處理程序。如果現有的建置系統極為複雜,則使用 Visual Studio 來重新建立建置系統所花費的時間,可能會對工作排程或期限造成不利的影響。

  • 遷移策略的優點。遷移現有的 makefile 通常會比較快速,並且您還可能運用開發人員現有的知識,以及整個系統的 makefile 和指令碼中儲存的資訊。

  • 遷移策略的缺點。雖然遷移策略有一些顯著的優點,但是您的 Windows 系統上需要有 make 公用程式的對等程式。 因為 make 會呼叫其他公用程式,所以 Windows 上也必須提供這些公用程式的對等程式,並且提供這些對等程式必須能夠安裝整個 UNIX 可攜性環境。

下一章將說明如何決定應該運用的策略,以及如何遷移建置系統。無論您將會採用哪一種策略,都會發現相當有助益的處理程序。如果您計劃使用 Visual Studio IDE 重新建立環境,或在 Windows 上使用 UNIX 可攜性環境,都能獲得相當有用的技術資訊。

顯示: