這是 Meson 最初的設計理念。它所描述的語法與發布的版本不符。
軟體開發人員最重要的工具是編輯器。如果你和程式設計師談論他們使用的編輯器,通常會聽到大量的熱情和讚美。你會聽到 Emacs 是有史以來最棒的東西,或者 vi 是如此優雅,或者 Eclipse 的整合功能如何讓你更有效率。你可以感受到人們對這些程式的熱情和喜愛。
第二重要的工具,甚至比編譯器更重要,是建置系統。
這些工具幾乎普遍受到鄙視。
你通常能得到的關於建置系統最正面的說法(可能需要一些哄騙)是類似於好吧,它是一個糟糕的系統,但所有其他選項更糟。 很容易理解為什麼會這樣。首先,常用的免費建置系統語法晦澀難懂。它們大多使用在隨機位置設定的全域變數,因此你永遠無法真正確定給定的程式碼行會做什麼。它們在每個轉彎處都會做奇怪且不可預測的事情。
讓我們用一個簡單的例子來說明這一點。假設我們想在 GDB 下執行使用 GNU Autotools 建置的程式。本能的做法是直接執行gdb programname
。問題是,這可能有效,也可能無效。在某些情況下,可執行檔是一個二進位檔案,而在其他時候,它是一個包裝 shell 腳本,它調用位於隱藏子目錄中的實際二進位檔案。如果二進位檔案是腳本,則 GDB 調用失敗,如果不是,則成功。使用者必須記住他每個可執行檔的類型(這是建置系統的實現細節),才能對它們進行偵錯。在這篇部落格文章中可以找到其他幾個這樣的痛點。
鑑於這些特質,難怪大多數人都不想與建置系統有任何關係。他們只會將在一個地方(在某種程度上)有效的程式碼複製貼上到另一個地方,並希望一切順利。他們會主動避免理解該系統,因為僅僅想到它就令人反感。這樣做也提供了一種反向的工作保障。如果你不了解工具 X,那麼你就會更少有可能發現自己負責在你的組織中使用它。相反,你可以從事更令人愉快的事情。
這導致了一個惡性循環。由於人們避免使用這些工具並且不想處理它們,因此很少有人致力於改進它們。結果是冷漠和停滯。
我們能做得更好嗎?
從本質上講,建置 C 和 C++ 程式碼並不是一項非常困難的任務。事實上,編寫文字編輯器要複雜得多,也需要更多的努力。然而,我們有很多高品質的編輯器,但只有少數建置系統的品質和可用性令人質疑。
因此,在「解決自身困擾」的偉大傳統中,我決定進行一項科學實驗。該實驗的目的是探索建立一個「良好」建置系統需要什麼。哪種語法適合這個問題?此應用程式需要解決哪些問題?哪種解決方案最合適?
首先,以下是任何現代跨平台建置系統都需要提供的一系列要求。
1. 必須易於使用
Python 的一大優點是它非常易於閱讀。很容易看出給定的程式碼區塊的作用。它簡潔、清晰且易於理解。提議的建置系統在語法和語義上必須是乾淨的。副作用、全域狀態和相互關係必須保持在最低限度,或者在可能的情況下完全消除。
2. 預設情況下必須做正確的事
大多數建置都是由開發人員在程式碼上進行的。因此,預設值必須針對該用例進行客製化。例如,系統應在不進行最佳化且具有偵錯資訊的情況下建置物件。它應建立可以從建置目錄直接執行的二進位檔案,而無需連結器技巧、shell 腳本或魔術環境變數。
3. 必須強制執行既定的最佳實務
確實沒有理由在沒有等效於 -Wall
的情況下編譯原始程式碼。因此,預設啟用它。另一種最佳實務是原始程式碼和建置目錄完全分離。所有建置成品都必須儲存在建置目錄中。在任何情況下都不允許在原始程式碼目錄中寫入雜散檔案。
4. 必須對常用平台提供原生支援
許多免費軟體專案可以在非免費平台上使用,例如 Windows 或 OSX。系統必須為這些平台上選擇的工具提供原生支援。在實務中,這意味著對 Visual Studio 和 XCode 的原生支援。讓 IDE 調用外部建置器二進位檔案不算是原生支援。
5. 不得因過時的平台而增加複雜性
這個建置系統的工作始於 2012 年的聖誕假期。這提供了一個 2012/12/24 的自然硬性截止線。當時未積極使用的任何平台、工具或程式庫都明確不受支援。其中包括 IRIX、SunOS、OSF-1 等 Unix 系統、早於 12/10 的 Ubuntu 版本、早於 4.7 的 GCC 版本等等。如果這些舊版本恰好可以工作,那就太好了。如果它們不能工作,系統將不會新增單行程式碼來解決它們的錯誤。
6. 必須快速
在中等大小的專案上執行組態步驟的時間不得超過五秒。在 1000 個原始程式碼檔案的完全最新的樹狀結構上執行編譯指令的時間不得超過 0.1 秒。
7. 必須為現代軟體開發功能提供易於使用的支援
一個例子是預編譯標頭。目前,沒有免費軟體建置系統為它們提供原生支援。其他例子可能包括輕鬆整合 Valgrind 和單元測試、測試覆蓋率報告等等。
8. 必須允許覆蓋預設值
有時你只需要使用指定的編譯器標誌編譯檔案,而沒有其他標誌,或者將檔案安裝在奇怪的位置。如果使用者真的想要這樣做,系統必須允許他這樣做。
解決方案概述
檢視這些要求,很明顯,唯一可行的做法與 CMake 採用的做法大致相同:使用領域特定語言來宣告建置系統。根據此宣告,為後端建置系統產生組態。這可以是 Makefile、Visual Studio 或 XCode 專案或任何其他內容。
擬議的 DSL 與現有 DSL 之間的區別在於,新的 DSL 是宣告式的。它也試圖在比現有系統更高的抽象層級上工作。例如,在目前的建置系統中使用外部程式庫意味著手動提取並傳遞編譯器標誌和連結器標誌。在擬議的系統中,使用者只是宣告給定的建置目標使用給定的外部相依性。然後,建置系統會負責將所有標誌和設定傳遞到它們的正確位置。這意味著使用者可以專注於自己的程式碼,而不是將命令列引數從一個地方傳送到另一個地方。
與 SCons 採用的方法(即將系統作為 Python 程式庫提供)相比,DSL 需要做更多的工作。但是,它可以讓我們使語法更具表現力,並透過例如使某些物件真正不可變來防止某些類型的錯誤。最終結果再次相同:減少使用者的工作量。
Unix 的後端需要更多考慮。預設選擇是 Make。但是它非常慢。在大程式碼庫上,Make 通常需要幾分鐘才能確定沒有任何事情需要做。我們沒有使用 Make,而是使用 Ninja,它非常快。後端程式碼與核心分離,因此可以相對輕鬆地新增其他後端。
範例程式碼
設計理念說得夠多了,讓我們開始看程式碼。在查看範例之前,我們要強調這絕不是最終的程式碼。它是概念驗證程式碼,在目前存在的系統中(2013 年 2 月)有效,但可能隨時變更。
讓我們從簡單開始。以下是編譯單個可執行二進位檔案的程式碼。
project('compile one', 'c')
executable('program', 'prog.c')
這算是最簡單的情況了。首先,你宣告專案名稱及其使用的語言。然後,你指定要建置的二進位檔案及其來源。建置系統將完成所有其他工作。它將新增正確的後綴(例如 Windows 上的「.exe」)、設定預設編譯器標誌等等。
通常,程式有多個來源檔案。將它們全部列在函式呼叫中可能會變得笨拙。這就是為什麼系統支援關鍵字引數的原因。它們看起來像這樣。
project('compile several', 'c')
sourcelist = ['main.c', 'file1.c', 'file2.c', 'file3.c']
executable('program', sources : sourcelist)
外部相依性易於使用。
project('external lib', 'c')
libdep = find_dep('extlibrary', required : true)
sourcelist = ['main.c', 'file1.c', 'file2.c', 'file3.c']
executable('program', sources : sourcelist, dep : libdep)
在其他建置系統中,你必須手動將外部相依性的編譯和連結標誌新增到目標中。在此系統中,你只需宣告 extlibrary 是強制性的,並且產生的程式會使用它。建置系統會為你完成所有管道。
以下是一個稍微複雜的定義。它應該仍然可以理解。
project('build library', 'c')
foolib = shared_library('foobar', sources : 'foobar.c',\
install : true)
exe = executable('testfoobar', 'tester.c', link : foolib)
add_test('test library', exe)
首先,我們建立一個名為 foobar 的共享程式庫。它被標記為可安裝,因此執行 meson install
會將其安裝到程式庫目錄(系統知道是哪個,因此使用者不必在意)。然後,我們建立一個連結到程式庫的測試可執行檔。它不會被安裝,而是被新增到單元測試清單中,可以使用 meson test
指令執行。
以上我們提到預編譯標頭是其他建置系統不支援的功能。以下是如何使用它們。
project('pch demo', 'cxx')
executable('myapp', 'myapp.cpp', pch : 'pch/myapp.hh')
其他建置系統無法如此輕鬆地提供 pch 支援的主要原因是它們不強制執行某些最佳實務。由於包含路徑的工作方式,不可能提供始終適用於原始程式碼和外部程式碼建置的 pch 支援。強制分離建置和原始程式碼目錄使得這和其他許多問題變得容易得多。
取得程式碼
此實驗的程式碼可在 Meson 儲存庫 中找到。應該注意的是(在撰寫本文時)它不是建置系統。它只是一個提案。它尚未可靠地工作。你可能不應將其用作專案的建置系統。
儘管如此,我希望這個實驗最終會變成一個成熟的建置系統。為此,我需要你的幫助。歡迎提出意見,尤其是修補程式。
搜尋結果是