perlhack - 如何對Perl進行黑客攻擊
本文解釋了Perl開發的運作方式。其中包括Perl 5 Porters郵件列表、Perl存儲庫、Perl錯誤跟蹤器、補丁指南以及對Perl開發理念的評論。
如果你只想提交一個小的補丁,比如pod修復、用於bug的測試、評論修復等,這很容易!以下是方法:
檢查源代碼庫
Perl源代碼位於git存儲庫中。你可以使用以下命令克隆存儲庫:
% git clone https://github.com/Perl/perl5.git perl
確保你遵循最新的建議
如果本指南中的建議最近有更新,直接從Perl源代碼中讀取最新版本
% perldoc pod/perlhack.pod
為你的更改創建一個分支
基於blead創建一個分支,將你的更改提交到該分支,稍後將用於將其發送到Perl錯誤跟蹤器
% git checkout -b mychange
進行你的更改
黑客攻擊,黑客攻擊,黑客攻擊。請記住,Perl運行在許多不同的平台上,擁有不同的操作系統,具有不同的功能,不同的文件系統組織,甚至不同的字符集。 perlhacktips 提供了相應的建議
測試你的更改
你可以運行以下命令來運行所有的測試
% ./Configure -des -Dusedevel
% make test
持續進行黑客攻擊,直到測試通過為止
提交你的更改
提交你的工作將保存更改在你的本地系統上
% git commit -a -m 'Commit message goes here'
請確保提交消息以一個句子描述你的更改。例如,"在perlhack.pod中修正了拼寫錯誤"
將你的更改發送到Perl錯誤跟蹤器
下一步是將你的補丁提交到Perl核心票證系統
在 GitHub 上建立 perl5 儲存庫的分支並將其添加為遠端,如果尚未完成,請參閱 GitHub 文件:https://help.github.com/en/articles/working-with-forks。
% git remote add fork git@github.com:MyUser/perl5.git
如需更多資訊,請參閱"使用 SSH 連線至 GitHub"。
如果您更傾向使用 HTTPS URL 進行 git push
,請參閱"使用 HTTPS URL 進行克隆"。
% git remote add fork https://github.com/MyUser/perl5.git
然後,將您的新分支推送到您的分支中。
% git push -u fork mychange
最後,按照 GitHub 文件的描述,在 GitHub 上從您的分支建立一個拉取請求到 blead:https://help.github.com/en/articles/creating-a-pull-request-from-a-fork。
謝謝您
開發者感謝您花費的時間幫助改進 Perl。謝謝!
致謝
所有貢獻者的名稱和電子郵件地址都會被記錄在 perl 發行版的 AUTHORS 文件中,以及 Git 提交歷史中。
如果您不希望被記錄在 AUTHORS 文件中,請告訴我們。否則,我們將以您提交的修補程式作為記錄您在 AUTHORS 文件中的授權。
下次
下次您希望提交修補程式時,您需要從最新的 perl 開始,保持原始狀態。請確認您的 perl 檢查中沒有任何本地更改或添加的檔案,然後執行這些命令
% git checkout blead
% git pull
% git reset --hard origin/blead
% git clean -dxf
如果您想要報告 Perl 中的錯誤,或瀏覽現有的 Perl 錯誤和修補程式,請使用 GitHub 的問題追蹤器:https://github.com/perl/perl5/issues。
在提交錯誤報告之前,請查看 perl5-porters 列表的存檔(見下文)和/或錯誤追蹤系統。通常,您會發現該錯誤已經被報告。
您可以登錄到錯誤追蹤系統並對現有的錯誤報告進行評論。如果您有關於現有錯誤的其他信息,請添加它。這將有助於開發者修復錯誤。
perl5-porters (p5p) 郵件列表是 Perl 標準發行版的維護和開發地點。維護 Perl 的人也被稱為 "Perl 5 Porters"、"p5p" 或只是 "porters"。
列表的可搜索存檔可在以下位置找到:https://markmail.org/search/?q=perl5-porters。還有一個存檔位於:https://archive.develooper.com/perl5-porters@perl.org/。
perl5-changes 郵件列表收到提交到 perl 庫維護和開發分支的每個补丁的副本。請參閱 https://lists.perl.org/list/perl5-changes.html 以獲取訂閱和存檔信息。
許多開發者也在 irc://irc.perl.org/#p5p 頻道上活躍。歡迎加入該頻道並就 Perl 核心的開發問題提問。
Perl 的所有源代碼都集中保存在 github.com 的 Git 存儲庫中。該存儲庫包含從 Perl 1 開始的許多 Perl 版本以及以前的版本控制系統 Perforce 的所有版本。
有關使用 Git 與 Perl 存儲庫的更多詳細信息,請參閱 perlgit。
您需要在計算機上安裝 Git。您可以使用 git 協議獲取存儲庫的副本。
% git clone git@github.com:Perl/perl5.git perl
這將克隆存儲庫並在 perl 目錄中創建一個本地副本。
如果由於防火牆原因無法使用 git 協議,您也可以通過 http 克隆。
% git clone https://github.com/Perl/perl5.git perl
您可以通過網絡訪問存儲庫。這使您可以瀏覽樹,查看最近的提交,訂閱存儲庫通知,搜索特定的提交等。您可以在 https://github.com/Perl/perl5 上訪問它。
如果您有提交權限,請參閱 perlgit 以獲取有關使用 Git 的更多詳細信息。
如果您計劃進行比單個小修補更廣泛的工作,我們鼓勵您閱讀下面的文檔。這將幫助您專注於工作並使您的补丁更容易融入 Perl 源代碼中。
如果您有一個小的修補程式要提交,請通過 GitHub Pull Request 流程提交。您也可以將修補程式發送到 p5p 列表。
修補程式在 GitHub 或 p5p 列表上進行審查和討論。簡單、無爭議的修補程式通常會在沒有任何討論的情況下應用。當修補程式應用後,票證將會更新,您將收到電子郵件。
在其他情況下,修補程式可能需要更多的工作或討論。我們鼓勵您參與討論並為您的修補程式辯護。有時您的修補程式可能會在忙碌中被遺忘。如果一個月內沒有採取任何行動,請給 p5p 發送一封提醒郵件是適當的。請記住,Perl 5 的開發人員都是志願者,請保持禮貌。
更改始終直接應用於主開發分支,稱為 "blead"。有些修補程式可能會被回溯應用到維護分支。如果您認為您的修補程式適合於維護分支(請參見perlpolicy 中的 "維護分支" 部分),請在提交時解釋原因。
如果您正在提交一個程式碼修補程式,有幾件事情可以幫助 Perl 5 Porters 接受您的修補程式。
使用 GitHub Pull Request 流程,您的修補程式將自動以適當的格式可用。如果您希望將修補程式提交到 p5p 列表進行審查,請確保創建它的方式適當。
如果您使用 git 檢查 Perl 源代碼,那麼使用 git format-patch
將會產生一個適合 Perl 風格的修補程式。format-patch
命令會為您所做的每次提交產生一個修補程式文件。如果您希望對所有提交使用單個修補程式,可以使用 git diff
。
% git checkout blead
% git pull
% git diff blead my-branch-name
這將產生一個基於 "blead" 和您當前分支之間差異的修補程式。在產生差異之前,確保 "blead" 是最新的是很重要的,這就是為什麼我們首先呼叫 git pull
。
我們強烈建議您使用 git 如果可能的話。這將使您的生活更輕鬆,也使我們的生活更輕鬆。
然而,如果您不使用 git,您仍然可以生成一個適合的修補程式。您需要一個原始的 Perl 源代碼副本來與之進行對比。開發人員更喜歡統一的差異。使用 GNU diff
,您可以生成如下所示的差異
% diff -Npurd perl.pristine perl.mine
確保在您的 Perl 副本中執行 make realclean
以刪除任何構建產物,否則您可能會得到混淆的結果。
當您製作每個打算提交到 Perl 核心的補丁時,撰寫好的提交訊息非常重要。如果您的提交將由一系列提交組成,這一點尤其重要。
提交訊息的第一行應該是一個沒有句號的簡短描述。最好不要超過電子郵件主題行的長度,50個字符是一個很好的參考準則。
許多 Git 工具(Gitweb、GitHub、git log --pretty=oneline等)在呈現提交摘要時只會顯示第一行(截斷到50個字符)。
提交訊息應該包括一個描述補丁正確的問題或新增功能的描述。
一般來說,您的提交訊息應該幫助了解 Perl 核心的程式設計師迅速了解您試圖做什麼,您試圖如何做以及為什麼對 Perl 進行更改很重要。
為什麼
您的提交訊息應該描述您正在進行的更改之重要性。當某人在六個月或六年後查看您的更改時,您的意圖應該清楚。
如果您打算廢棄一個功能以後簡化其他部分的代碼,請說明。如果您正在解決性能問題或添加新功能以支持核心的其他部分,請提及。
什麼
您的提交訊息應該描述您正在更改的 Perl 核心的哪部分以及您期望您的補丁執行的操作。
如何
雖然對於文檔更改、新測試或微不足道的補丁來說並不是必需的,但通常值得解釋您的更改是如何工作的。即使今天對您來說很清楚,對於下個月或明年的一個移植者可能並不清楚。
提交訊息並不是用來取代您的代碼中的註釋的。提交訊息應該描述您所做的更改,而代碼註釋應該描述代碼的當前狀態。
如果您剛實現了一個新功能,包括文檔、測試和註釋完善的代碼,一個簡短的提交訊息通常就足夠了。但是,如果您只是在解析器或詞法分析器中更改了一個字符,您可能需要寫一個小說來確保將來的讀者了解您做了什麼以及為什麼這樣做。
請務必對代碼進行充分的註釋。雖然每行註釋都是不必要的,但任何利用運算符的副作用,創建將在被修補的函數之外感知到的變化,或者他人可能會感到困惑的事物都應該進行文檔化。如果要出錯,添加太多註釋比添加太少更好。
最好的註釋解釋代碼為何執行特定操作,而不是單純描述它的功能。
一般而言,請遵循您正在修補的代碼的特定風格。
特別是,遵循以下一般指南來修補 Perl 源代碼
代碼的縮排為 4 個空格,嵌套 CPP 的 #define
為 2 個空格,補全為 8 個空格。
使用空格進行縮排,而不是制表符。
代碼庫中的縮排使用了制表符和空格的混合方式,我們正在遷移到僅使用空格。將您正在修補的行從 8 個空格的制表符轉換為空格將有助於此遷移。
盡量不要超過 79 個列
一般而言,我們以 80 列為目標。當保持在 80 列會導致代碼繁瑣或需要重做時,可以稍微超出。請盡量減少超過 80 列的部分。
ANSI C 原型
不要將 else 與相應的 if 縮排在同一行,對於縮排控制結構使用 "K&R" 風格
不使用 C++ 風格 (//) 註釋
使用 XXX 標記需要重新檢查的地方(並經常重新檢查!)
當條件跨越多行時,開始的大括號與 "if" 對齊;否則應該在行尾
在函數定義中,名稱從第 0 列開始(返回值類型位於上一行)
關鍵字後跟括號的地方後面加一個空格,函數名稱和後面的括號之間不加空格
盡量避免在條件語句中進行賦值,但如果不可避免,請使用額外的括號,例如 "if (a && (b = c)) ..."
使用 "return foo;" 而不是 "return(foo);"
使用 "if (!foo) ..." 而不是 "if (foo == FALSE) ..." 等
不要使用 "register" 關鍵字聲明變量。它可能會對現代編譯器產生負面影響,在經常編譯 Perl 源代碼的 C++ 下被廢棄。
可從 XS 代碼訪問的頭文件中的內嵌函數需要能夠使用常用的額外編譯標誌編譯而不產生警告,例如 gcc 的 -Wswitch-default
,它在 switch 語句沒有 "default" 情況時會發出警告。這些額外標誌的使用是為了捕捉合法 C 代碼中的潛在問題,並且通常被 Perl 聚合器(例如 Linux 發行版)使用。
如果您的補丁更改了代碼(而不僅僅是更改文檔),則您還應包括一個或多個測試案例,這些案例說明您正在修復的錯誤或驗證您正在添加的新功能。一般而言,您應該更新現有的測試文件,而不是創建新的測試文件。
您的測試套件補充應該遵循這些指南(由 Gurusamy Sarathy <gsar@activestate.com> 提供)
了解你正在測試的內容。閱讀文檔和源代碼。
往往是失敗,而不是成功。
嚴格解釋結果。
使用不相關的功能(這將暴露出奇怪的交互作用)。
使用非標準成語(否則你就不是在測試 TIMTOWTDI)。
盡可能避免使用硬編碼的測試數字(在 t/op/tie.t 中找到的 EXPECTED/GOT 更易於維護,並提供更好的錯誤報告)。
當測試失敗時提供有意義的錯誤消息。
除非你正在測試它們,否則避免使用 qx// 和 system()。如果你使用它們,請確保覆蓋 _所有_ perl 平台。
刪除你創建的任何臨時文件。
將未預見的警告提升為錯誤,使用 $SIG{__WARN__}。
確保使用正在測試的版本隨附的庫和模塊,而不是已安裝的那些。
向代碼中添加注釋,解釋你正在測試什麼。
使更新 '1..42' 字符串無需。或者確保你更新它。
測試給定運算符、庫或函數的 _所有_ 行為。
測試所有可選參數。
在各種上下文中測試返回值(布爾值、純量、列表、左值)。
使用全局和詞法變量。
不要忘記特殊的、病態的情況。
這與修補其他內容的方式相同,只是多了一個考慮因素。
源代碼樹中 cpan/ 目錄中的模塊是在 Perl 核心之外維護的。當作者更新模塊時,更新就會被簡單地複製到核心中。有關在 https://metacpan.org/ 上報告錯誤和提交修補程序的更多信息,請參閱該模塊的文檔或其列表。
在大多數情況下,對 cpan/ 中的模塊進行的修補應該發送到上游,而不應該單獨應用到 Perl 核心。如果對 cpan/ 中的文件的修補絕對不能等待修補上游,發佈到 CPAN,並複製到 blead,您必須添加(或更新) Porting/Maintainers.pl 文件中的 CUSTOMIZED
項目以標記進行了本地修改。有關更多詳情,請參閱 Porting/Maintainers.pl。
相反地,dist/ 目錄中的模組是在核心中維護的。
對於足以需要 pod/perldelta.pod 條目的重大更改,如果您提交實際更改與您的 delta 條目,開發人員將非常感激。重大更改包括但不限於
添加、廢棄或刪除核心功能
添加、廢棄、刪除或升級核心或雙生命模組
添加新的核心測試
修復核心中的安全問題和用戶可見的錯誤
可能破壞現有代碼的更改,無論是在 Perl 還是 C 層面
重大性能改進
在 pod/ 目錄中添加、刪除或重大更改文件
重要的特定平台更改
請確保將 perldelta 條目添加到 pod/perldelta.pod 中的正確部分。有關如何撰寫良好的 perldelta 條目的更多信息,請參閱 Porting/how_to_write_a_perldelta.pod 中的 Style
部分。
對於語言的新功能和擴展可能會引起爭議。沒有一套特定的標準來確定哪些功能會被添加,但在開發補丁時可以考慮以下問題
我們的目標包括但不限於
保持快速、簡單和有用。
盡可能使功能/概念正交。
沒有任意限制(平台、數據大小、文化)。
使 Perl 在各處開放且令人興奮地使用/補丁/倡導。
要麼吸收新技術,要麼與它們建立橋樑。
只談論而不實現是毫無意義的。幾乎在每種情況下,爭論要求添加新功能的人將被期望是實現它們的人。能夠編寫新功能的開發人員有他們自己的議程,並且不會為您(可能是好的)想法實現它們。
破壞現有 Perl 程序是一個致命的錯誤。新警告可能會引起爭議——有人說發出警告的程序沒有問題,而其他人說有問題。添加關鍵字可能會破壞程序,改變現有標記序列或函數的含義可能會破壞程序。
Perl 5 核心包括幫助開發人員使向後不兼容的更改更加兼容的機制,例如 feature 和 deprecate 模組。請在適當時使用它們。
Perl 5 具有擴展機制,模組和 XS,特別是為了避免不斷改變 Perl 解譯器的需要。您可以撰寫導出函數的模組,可以給這些函數添加原型,使其可以像內置函數一樣調用,甚至可以撰寫 XS 代碼來操作 Perl 解譯器的運行時數據結構,以實現非常複雜的功能。
在可能的情況下,新功能應該在 CPAN 模組中進行原型設計,然後才會考慮納入核心功能。
這是否只是提交者想要添加到語言中的功能,還是廣泛可用?有時,端口可能會決定等待某人實現更通用的功能,而不是添加具有狹窄焦點的功能。
對 Perl 解譯器的大規模重寫可能會引入新的錯誤。
變更越小且局部化,越好。同樣,一系列小补丁比單個大补丁更受歡迎。
如果一個补丁封閉了未來的發展方向,則可能會被拒絕。例如,一個對原型定義施加真實和最終解釋的补丁可能會被拒絕,因為對於原型未來的選擇還沒有得到解決。
好的补丁(代碼緊湊,完整,正確)更有可能被接受。粗糙或不正確的补丁可能被擱置,直到修復完成,或者可能完全被丟棄,而不再進行通知。
最糟糕的补丁使用了特定於系統的功能。非通用的 Perl 語言附加功能很可能不會被接受。
更改行為的补丁(修復錯誤或引入新功能)必須包含回歸測試,以驗證一切是否按預期運行。
沒有原始作者提供的測試,未來更改 perl 的任何其他人如何確定他們沒有無意中破壞补丁實現的行為?沒有測試,补丁的作者如何確信他/她的辛勤工作不會被未來的某個人無意中丟棄?
沒有文件說明的補丁可能是沒有好好考慮或不完整的。沒有文件說明,就不能添加或更改功能,因此提交適當 pod 文件的補丁以及源代碼是很重要的。
拉里說:“雖然 Perl 的口號是有更多的方法來做到這一點,但我不願意讓一個事情有 10 種做法”。然而,這是一個棘手的啟發式方法--一個人認為必要的添加,對另一個人來說可能是毫無意義的累贅。
對於提交者、Perl 程序員、模組作者等都是一種工作,... Perl 應該是易於使用的。
有效的程式碼總是比虛幻的想法更受歡迎。添加功能的補丁比隨機的功能請求更有可能被添加到語言中,無論請求者如何熱烈地爭論。這也涉及到“它是否有用?”的問題,因為某人花時間製作補丁表明對功能的強烈渴望。
核心使用與 Perl 其他部分相同的測試方式,通過 Test::Harness 簡單地運行“ok/not ok”,但有一些特殊考量。
在核心中有三種方式編寫測試:Test::More、t/test.pl和臨時的 print $test ? "ok 42\n" : "not ok 42\n"
。選擇使用哪一種取決於您正在工作的測試套件的部分。這是為了防止高層次的失敗(例如 Config.pm 断裂)導致基本功能測試失敗的措施。
t/test.pl 库提供了一些 Test::More 的功能,但避免了加載大多數模組,並且盡可能少使用核心功能。
如果您自己編寫測試,請使用測試任意協定。
t/base、t/comp 和 t/opbasic
由於我們不確定 require
是否有效,甚至子程式是否有效,因此對這三個功能進行了臨時測試。請謹慎行事,以避免使用正在測試的功能。例如,t/opbasic 中的測試被放在那裡,而不是 t/op 中,因為它們測試了 t/test.pl 假設已經被證明有效的功能。
t/ 下的所有其他子目錄
現在基本的 require() 和子程式已經測試過了,你可以使用 t/test.pl 函式庫。
你還可以有條件地使用像 Config 這樣的函式庫,但如果它不存在,請確保優雅地跳過測試。
在 t/ 下找不到的測試檔案
這個類別包括在 dist、ext 和 lib 等目錄下的 .t 檔案。由於 Perl 核心已經經過測試,現在可以並且應該使用 Test::More。你還可以在測試中使用全部核心模組套件。(如上所述,對於在 cpan/ 下找到的 .t 檔案的更改應提交給這些模組的上游維護者。)
當你執行 "make test" 時,Perl 使用 t/TEST 程式來運行測試套件(在 Win32 下使用 t/harness 代替)。所有測試都是從 t/ 目錄運行的,而不是從包含測試的目錄運行的。這會導致在 lib/ 中的測試出現一些問題,因此這裡有機會進行一些修補。
你必須特別注意跨平台的問題。這通常歸結為使用 File::Spec,避免使用像 fork()
和 system()
這樣的功能,除非絕對必要,並且不要假設給定的字符具有特定的序數值(編碼點)或其 UTF-8 表示形式由特定的字節組成。
測試中有幾個可用於可移植指定字符和編碼點的函式。始終預載的函式 utf8::unicode_to_native()
及其反函式 utf8::native_to_unicode()
接受編碼點並進行適當的轉換。檔案 t/charset_tools.pl 中有一些可能有用的函式。它具有接受字符串作為輸入的前兩個函式的版本 - 而不是單個數字編碼點: uni_to_native()
和 native_to_uni()
。如果你必須查看 UTF-8 編碼字符串的個別字節,則 byte_utf8a_to_utf8n()
接受編碼為 ASCII 平台的字節的字符串作為輸入,並返回本機平台上的等效字符串。例如,byte_utf8a_to_utf8n("\xC2\xA0")
返回當前平台上形成 U+00A0
的 UTF-8 的字節序列,因為 "\xC2\xA0"
是該代碼點在 ASCII 平台上的 UTF-8 字節。該函式在 ASCII 平台上返回 "\xC2\xA0"
,在 EBCDIC 1047 平台上返回 "\x80\x41"
。
但最簡單的方法是,如果字符可以指定為文字,例如 "A"
或 "%"
,則使用它; 如果無法這樣指定,則可以使用 \N{}
,如果副作用不麻煩的話。只需使用十六進制指定所有字符,使用 \N{U+ZZ}
而不是 \xZZ
。 \N{}
是 Unicode 名稱,因此它始終給出 Unicode 字符。 \N{U+41}
是其 Unicode 代碼點為 0x41
的字符,因此在所有平台上都是 'A'
。副作用是
這些是選擇性的 Unicode 規則。這意味著在雙引號字符串中,字符串總是轉換為 UTF-8 以強制進行 Unicode 解釋(您之後可以使用 utf8::downgrade()
將其轉換回非 UTF8,如果可能的話)。在正則表達式模式中,不執行轉換,但如果字符集修改器否則將是 /d
,則將其更改為 /u
。
如果使用形式 \N{字符名稱}
,則將自動加載 charnames 模塊。這可能不適用於您正在進行的測試級別。
如果正在測試區域設置(請參閱 perllocale),則在 t/loc_tools.pl 中有幫助函數,可讓您查看當前平台上有哪些區域設置。
make test
目標有各種特殊的 make 目標可用於以略有不同於標準 "test" 目標的方式測試 Perl。並非所有目標都預期能夠達到 100% 的成功率。其中許多具有多個別名,並且其中許多在某些操作系統上不可用。
test_porting
這會在源代碼樹上運行一些基本的健全性測試,並有助於在提交補丁之前捕獲基本錯誤。
minitest
在 t/base、t/comp、t/cmd、t/run、t/io、t/op、t/uni 和 t/mro 測試中運行 miniperl。
miniperl 是一個精簡的 Perl,用於啟動構建擴展、實用程序、文檔等。它不支持動態加載,並且根據構建過程中的點,只能訪問有限的核心模塊集。 miniperl 不適用於日常使用。
test.valgrind check.valgrind
(僅在 Linux 中)使用內存泄漏 + 頑皮內存訪問工具 "valgrind" 運行所有測試。日志文件將命名為 testname.valgrind。
test_harness
使用 t/harness 控制程序而不是 t/TEST 運行測試套件。 t/harness 更複雜,並使用 Test::Harness 模塊,因此假設 perl 大部分工作。對於我們的目的,主要優點是它在結尾處打印了失敗測試的詳細摘要。此外,與 t/TEST 不同,它不會將 stderr 重定向到 stdout。
請注意,在 Win32 下,始終使用 t/harness 而不是 t/TEST,因此沒有特殊的 "test_harness" 目標。
在 Unix 建置過程中,您可以使用 TEST_ARGS 和 TEST_FILES 參數將參數傳遞給底層的測試鏈接調用。這意味著例如您可以執行
make test_harness TEST_ARGS="-v -re pat"
這將編譯並運行測試鏈接,並以詳細模式運行包含 "pat" 的文件。或者您可以執行
make test_harness TEST_ARGS="-torture" TEST_FILES="op/*.t"
並對與 glob "op/*.t" 匹配的文件執行壓力測試。
在 Win32 的 "test" 目標下,您可以使用 TEST_SWITCHES 和 TEST_FILES 環境變量來控制 t/harness 的行為。這意味著您可以執行
nmake test TEST_FILES="op/*.t"
nmake test TEST_SWITCHES="-torture" TEST_FILES="op/*.t"
請注意,為了與 Unix 建置過程兼容,TEST_ARGS 也可以用來替代傳統的 TEST_SWITCHES 參數。
test-notty test_notty
在運行正常測試之前將 PERL_SKIP_TTY_TEST 設置為 true。
核心發行版現在可以在類 Unix 和 Windows 平台上並行運行其回歸測試。在 Unix 上,不要運行 make test
,而是在環境中設置 TEST_JOBS
為要並行運行的測試數量,然後運行 make test_harness
。在類 Bourne 的 shell 上,可以這樣做
TEST_JOBS=3 make test_harness # Run 3 tests in parallel
使用環境變量,而不是並行 make 本身,是因為 TAP::Harness 需要能夠自己安排單個不衝突的測試腳本,而且沒有標準界面可與它們的作業調度器交互。
測試通常按邏輯順序運行,首先是完整性測試,然後是 Perl 核心功能的主要測試,然後是非核心模塊的測試。在許多核心系統上,這可能不會有效地使用硬件。通過還指定
TEST_JOBS=19 PERL_TEST_HARNESS_ASAP=1 make -j19 test_harness
您表明您希望測試以最短的實際時間完成。在完整性測試完成後,這導致其餘測試被緊密地打包到可用的核心中,以我們所知的方式。這對於較慢的多核系統效果最好。在一個過時的 24 核系統上,吞吐量提高了 20%;在較新的更快的系統上,核心較少。
請注意,上面的命令行添加了一個 -j
參數到 make,以便導致並行編譯。這在您的平台上可能有效或無效。
通常,測試花費的時間數據存儲在 t/test_state 中,但是您可以通過將 PERL_TEST_STATE_FILE
環境變量設置為其他文件名來更改這一點,或者設置為假值(0 或空字符串)以完全禁用狀態機制的使用。對狀態文件格式的變化沒有保護,因此如果您有與此文件相關的任何問題,您需要手動刪除文件,然後讓鏈接重新創建它,儘管文件格式不經常更改,因此這應該不會經常需要。
您可以透過在 t/ 目錄下使用以下命令之一手動執行測試套件的一部分
./perl -I../lib TEST list-of-.t-files
或者
./perl -I../lib harness list-of-.t-files
(如果您沒有指定測試腳本,將運行整個測試套件。)
如果您使用 harness
進行測試,您可以使用幾個命令行選項。這些參數按照必須出現的順序列出如下:
harness -v -torture -re=pattern LIST OF FILES TO TEST
harness -v -torture -re LIST OF PATTERNS TO MATCH
如果省略了 要測試的文件列表
,則文件列表將從清單中獲取。文件列表可能包含通配符,這些通配符將被展開。
-v
以詳細模式運行測試,以便您可以看到運行了哪些測試以及調試輸出。
-torture
運行 torture 測試以及正常集。
-re=PATTERN
過濾文件列表,使所有運行的測試文件都匹配 PATTERN。請注意,這種形式與下面的 -re LIST OF PATTERNS 形式不同,因為它允許提供文件列表。
-re LIST OF PATTERNS
過濾文件列表,使所有運行的測試文件都匹配 /(LIST|OF|PATTERNS)/。請注意,使用此形式時,模式是由 '|' 連接的,您不能提供文件列表,而是從 MANIFEST 獲取測試文件。
您可以通過類似以下的命令運行單個測試
./perl -I../lib path/to/foo.t
但是測試套件設置了一些可能會影響測試執行的環境變量
PERL_CORE=1
表示我們將此測試作為 Perl 核心測試套件的一部分運行。對於在 CPAN 上具有雙重生命的模塊非常有用。
PERL_DESTRUCT_LEVEL=2
如果尚未設置,則設置為 2 (參見 "perlhacktips 中的 PERL_DESTRUCT_LEVEL")。
PERL
(僅由 t/TEST 使用) 如果設置,將覆蓋要用於運行測試的 perl 執行文件的路徑(默認為 ./perl)。
PERL_SKIP_TTY_TEST
如果設置,告訴跳過需要終端的測試。實際上,Makefile 會自動設置它,但也可以通過運行 'make test_notty' 來強制設置。
PERL_TEST_Net_Ping
設置此變數將運行所有 Net::Ping 模組的測試,否則將跳過一些與外界互動的測試。請參閱 perl58delta。
PERL_TEST_NOVREXX
設置此變數將跳過 OS2::REXX 的 vrexx.t 測試。
PERL_TEST_NUMCONVERTS
這將在 op/numconvert.t 中設置一個變數。
PERL_TEST_MEMORY
設置此變數將包括 t/bigmem/ 中的測試。這應該設置為可用於測試的內存的 gigabytes 數量,例如,PERL_TEST_MEMORY=4
表示可以安全地運行需要 4GiB 可用內存的測試。
另請參閱 Test 和 Test::Harness 模組的文檔,以了解更多影響測試的環境變數。
文件 t/perf/benchmarks 包含了預期通過 Porting/bench.pl 工具對一系列 Perl 進行基準測試的 Perl 代碼片段。如果您修復或增強了性能問題,您可能希望將一個代表性的代碼樣本添加到文件中,然後運行 bench.pl 對先前和當前的 Perl 進行基準測試,以查看其所做的差異,以及是否有其他東西因此變慢了。
文件 t/perf/opcount.t 設計用於測試特定代碼片段是否已編譯為包含指定數量特定 op 類型的 optree。這對於測試是否進行了修改 op 的優化,例如將 aelem
op 轉換為 aelemfast
op,非常有用。
文件 t/perf/speed.t 和 t/re/speed.t 設計用於測試如果某個優化被破壞,會使某些操作變得數千倍更慢的事物(例如,長 utf8 字符串上的 utf8 長度緩存)。添加一個測試,正常情況下需要幾分之一秒,否則需要幾分鐘,導致測試文件在失敗時超時。
在 Perl 核心發行版上進行修改的過程中,您可能會需要在舊的提交上配置、構建和測試 Perl。有時候,在此過程中 make
會失敗。如果發生這種情況,您可以嘗試使用來自 CPAN 的 Devel::PatchPerl 库(未包含在核心中)將該提交的源代碼轉換為可構建的狀態。
這裡有一個真實世界的例子,取自於解決 perl #10118 的工作。使用 Porting/bisect.pl 已經識別出提交 ba77e4cc9d1ceebf472c9c5c18b2377ee47062e6
是一個錯誤被修正的提交。為了確認,一位 P5P 開發者想要在提交 ba77e4c^
(推測為“不好”)和 ba77e4c
(推測為“好”)上配置並構建 perl。嘗試了正常的配置和構建。
$ sh ./Configure -des -Dusedevel
$ make test_prep
make
,然而,失敗並輸出(節錄)如下:
cc -fstack-protector -L/usr/local/lib -o miniperl \
gv.o toke.o perly.o pad.o regcomp.o dump.o util.o \
mg.o reentr.o mro.o hv.o av.o run.o pp_hot.o sv.o \
pp.o scope.o pp_ctl.o pp_sys.o doop.o doio.o regexec.o \
utf8.o taint.o deb.o universal.o globals.o perlio.o \
numeric.o mathoms.o locale.o pp_pack.o pp_sort.o \
miniperlmain.o opmini.o perlmini.o
pp.o: In function `Perl_pp_pow':
pp.c:(.text+0x2db9): undefined reference to `pow'
...
collect2: error: ld returned 1 exit status
makefile:348: recipe for target 'miniperl' failed
make: *** [miniperl] Error 1
另一位 P5P 貢獻者建議在這種情況下安裝並使用 Devel::PatchPerl,首先確定提交的 perl 版本,然後在該點修補源代碼以便進行構建。
$ perl -MDevel::PatchPerl -e \
'print Devel::PatchPerl->determine_version("/path/to/sourcecode"),
"\n";'
5.11.1
$ perl -MDevel::PatchPerl -e \
'Devel::PatchPerl->patch_source("5.11.1", "/path/to/sourcecode");'
一旦源代碼被修補,就呼叫了 ./Configure
和 make test_prep
並成功完成,從而確認了 RT#72414 中的發現。
要修改 Perl 的核心,您需要閱讀以下資料
Perl 源代碼樹的概述。這將幫助您找到您要尋找的文件。
Perl 解譯器源代碼的概述以及有關 Perl 如何執行操作的一些細節。
此文檔介紹了對 Perl C 代碼進行小修補的過程。如果您剛開始進行 Perl 核心開發,這將幫助您了解其工作原理。
有關 Perl 核心開發的更多細節。該文檔聚焦於較低層次的細節,如如何編寫測試、編譯問題、可移植性、調試等。
如果您打算進行嚴肅的 C 代碼開發,請確保閱讀此文檔。
這是至關重要的,因為它是 Perl 源代碼中的各個部分放置位置的文檔。反復閱讀幾次,它可能開始變得有意義 - 如果它還不明白,請不要擔心,因為最好的學習方法是與查看 Perl 源代碼並行閱讀它,我們稍後會進行這樣的學習。
Gisle Aas 的 "illustrated perlguts",也被稱為 illguts,有非常有用的圖片
對於核心開發來說,對 XSUB 編程的工作知識非常有用;XSUB 使用從 PP 代碼中提取的技術,PP 代碼是實際執行 Perl 程序的核心部分。從簡單的示例和解釋中學習這些技術比從核心本身學習要容易得多。
Perl API 的文檔解釋了一些內部函數的功能,以及源代碼中使用的許多宏。
轉接/南瓜.pod
這是一個給Perl轉接者的智慧之言集合;其中一部分僅對南瓜持有者有用,但大部分適用於任何想要進行Perl開發的人。
CPAN 測試員(http://cpantesters.org/)是一群志願者,他們在各種平台上測試 CPAN 模組。
Perl Smokers(https://www.nntp.perl.org/group/perl.daily-build/ 和 https://www.nntp.perl.org/group/perl.daily-build.reports/)自動在具有各種配置的平台上測試 Perl 源代碼發布。
這兩項努力都歡迎志願者加入。要參與 smoke 測試 Perl 本身,請訪問 https://metacpan.org/release/Test-Smoke。要開始 smoke 測試 CPAN 模組,請訪問 https://metacpan.org/release/CPANPLUS-YACSmoke 或 https://metacpan.org/release/minismokebox 或 https://metacpan.org/release/CPAN-Reporter。
如果您已經閱讀了本文檔中的所有文檔以及上面列出的文檔,那麼您已經準備好開始對Perl進行開發了。
以下是一些更多的建議
訂閱 perl5-porters,關注補丁並試著理解它們;如果您對某部分不清楚,請毫不猶豫地提問 - 誰知道,您可能會在補丁中發現一個 bug...
請閱讀與您的操作系統相關的 README,例如在 IBM AIX 操作系統上的 README.aix。如果您發現任何缺失或在新的操作系統發布中發生變化的地方,請勇於提供補丁給該 README。
找到一個對您感興趣的Perl領域,並試著弄清楚它是如何運作的。通過源代碼進行掃描,並在調試器中逐步跟踪它。玩耍,摸索,調查,進行實驗!您可能不僅會了解您選擇的領域,還可能比您想像的更早地了解到Perl的更廣泛活動範圍。
如果您能做到這些事情,您已經踏上了Perl轉接的漫長道路。感謝您想要幫助改進Perl - 祝您愉快地進行編程!
如果您認識上面有關道路的引用,那麼您很幸運。
大多數軟體項目在每個文件開頭都會有一個對該文件用途的文字描述。而Perl則是以文學典故開始每個文件的用途。
像許多書籍的章節一樣,所有頂級 Perl 源代碼文件(以及偶爾出現的一些其他文件)都以一句寓意深遠的題詞開始,間接而隱喻地指向你即將閱讀的內容。
引文取自J.R.R.托爾金有關他的虛構世界的著作,幾乎都來自《魔戒》。章節和頁碼使用以下版本提供:
霍比特人,作者J.R.R.托爾金。使用的是2007年出版的70週年硬面版本,由英國哈珀柯林斯出版社和美國霍頓·米夫林公司出版。
魔戒,作者J.R.R.托爾金。使用的是2004年出版的50週年硬面版本,由英國哈珀柯林斯出版社和美國霍頓·米夫林公司出版。
貝勒蘭的詩歌,作者J.R.R.托爾金,由其兒子兼文學執行人C.J.R.托爾金在其龐大的中土歷史的12卷中後humously出版。頁碼來源於1983年由George Allen&Unwin首次出版的硬面版本;2002年的特別三卷合集版或各種平裝版本的頁碼沒有變化,這些版本現在都是由哈珀柯林斯或霍頓·米夫林出版。
其他J.R.R.托爾金的著作,如汤姆·邦巴迪尔历险记、精灵宝钻、未完成的故事和胡林之子的故事,除了第一本由CJRT后humously集合外,都可以引用。但是,《魔戒》本身是完全可以引用的,可能是最好的引用來源,只要你能在那裡找到合適的引文。
因此,如果您要提供一個新的、完整的、頂級的源文件來添加到 Perl 中,您應該遵循這個奇怪的做法,自己從托爾金的著作中選擇一個適當的引文,保留原始的拼寫和標點,並使用與其餘引文相同的格式。間接和拐彎抹角是完全可以的;請記住,這是一個比喻,所以元是它的用途。
本文最初由Nathan Torkington撰寫,由perl5-porters郵件列表維護。