☰ OCaml 工具
第 16 章 原生碼編譯 (ocamlopt)
本章描述 OCaml 高效能原生碼編譯器 ocamlopt ,它將 OCaml 原始碼檔案編譯為原生碼物件檔案,並連結這些物件檔案以產生獨立的可執行檔。
原生碼編譯器僅在某些平台上可用。它產生的程式碼執行速度比 ocamlc 產生的位元組碼快,但代價是編譯時間和可執行程式碼大小增加。與位元組碼編譯器的相容性非常高:當使用 ocamlc 和 ocamlopt 編譯時,相同的原始碼應該以相同的方式執行。
無法將 ocamlopt 產生的原生碼物件檔案與 ocamlc 產生的位元組碼物件檔案混合使用:程式必須完全使用 ocamlopt 或完全使用 ocamlc 編譯。ocamlopt 產生的原生碼物件檔案無法載入頂層系統 ocaml 。
1 編譯器概觀
ocamlopt 命令的命令列介面與 ocamlc 非常接近。它接受相同類型的引數,並在處理完所有選項後依序處理它們。
連結階段的輸出是常規的 Unix 或 Windows 可執行檔。它不需要 ocamlrun 即可執行。
編譯器能夠發出關於其內部階段的一些資訊
2 選項
ocamlopt 可識別下列命令列選項。選項 -pack 、-a 、-shared 、-c 、-output-obj 和 -output-complete-obj 是互斥的。
-a 使用命令列上給定的物件檔案(.cmx 和 .o /.obj 檔案)建置函式庫(.cmxa 和 .a /.lib 檔案),而不是將它們連結到可執行檔案中。函式庫的名稱必須使用 -o 選項設定。如果在命令列上傳遞了 -cclib 或 -ccopt 選項,這些選項會儲存在產生的 .cmxa 函式庫中。然後,連結此函式庫會自動新增 -cclib 和 -ccopt 選項,就像它們在命令列上提供一樣,除非給定 -noautolink 選項。
-absname 強制錯誤訊息顯示檔案名稱的絕對路徑。 -no-absname 請勿嘗試在錯誤訊息中顯示絕對檔案名稱。 -annot 自 OCaml 4.11 版起已過時。請改用 -bin-annot 。 -args filename 從 filename 讀取其他以換行符號結尾的命令列引數。 -args0 filename 從 filename 讀取其他以空字元結尾的命令列引數。 -bin-annot 以二進位格式傾印有關編譯的詳細資訊(類型、繫結、尾呼叫等)。檔案 src .ml (或 src .mli )的資訊會放入檔案 src .cmt (或 src .cmti )。如果發生類型錯誤,請在錯誤之前傾印類型檢查器推斷的所有資訊。-bin-annot 產生的 *.cmt 和 *.cmti 檔案比 -annot 產生的檔案包含更多資訊,而且更精簡。 -c 僅編譯。抑制編譯的連結階段。原始碼檔案會被轉換為編譯後的檔案,但不產生可執行檔。此選項對於分別編譯模組非常有用。 -cc ccomp 使用 ccomp 作為 C 連結器,用於建置最終可執行檔,並作為 C 編譯器,用於編譯 .c 原始碼檔案。當連結由 C++ 編譯器(例如 g++ 或 clang++ )產生的目標檔案時,建議使用 -cc c++ 。 -cclib -l libname 將 -l libname 選項傳遞給連結器。這會導致給定的 C 函式庫與程式連結。 -ccopt option 將給定的選項傳遞給 C 編譯器和連結器。例如,-ccopt -L dir 會導致 C 連結器在目錄 dir 中搜尋 C 函式庫。 -cmi-file filename 使用給定的介面檔案來類型檢查要編譯的 ML 原始碼檔案。如果未指定此選項,編譯器會尋找與它正在編譯的實作具有相同基本名稱且位於相同目錄中的 .mli 檔案。如果找到此類檔案,編譯器會在包含的目錄中尋找對應的 .cmi 檔案,如果找不到,則會報告錯誤。 -color mode 啟用或停用編譯器訊息中的色彩(尤其是警告和錯誤)。支援以下模式
auto 僅當輸出支援色彩時,才使用啟發式方法啟用色彩(ANSI 相容的 tty 終端機); always 無條件啟用色彩; never 停用色彩輸出。 如果未提供 -color ,則會考慮環境變數 OCAML_COLOR 。其值如上,為 auto/always/never。
如果未提供 -color ,OCAML_COLOR 未設定且設定了環境變數 NO_COLOR ,則會停用色彩輸出。否則,預設設定為「auto」,且目前的啟發式方法會檢查 TERM 環境變數是否存在且不為空或 dumb ,並且「isatty(stderr)」成立。
-error-style mode 控制錯誤訊息和警告的列印方式。支援以下模式
short 僅列印錯誤及其位置; contextual 與 short 類似,但也會顯示對應於錯誤位置的原始碼片段。 預設設定為 contextual 。如果未提供 -error-style ,則會考慮環境變數 OCAML_ERROR_STYLE 。其值如上,為 short/contextual。
-compact 針對空間而非時間最佳化產生的程式碼。這會產生稍微小但稍微慢的程式。預設為針對速度進行最佳化。 -config 列印 ocamlopt 的版本號碼及其組態的詳細摘要,然後結束。 -config-var var 列印來自 -config 輸出的特定組態變數的值,然後結束。如果變數不存在,則結束代碼為非零。此選項僅自 OCaml 4.08 起可用,因此指令碼作者應為較舊版本提供後備選項。 -depend ocamldep-args 計算相依性,如同 ocamldep 命令所做的那樣。其餘引數會被解讀為如同它們已提供給 ocamldep 命令。 -for-pack module-path 產生一個目標檔案(.cmx 和 .o /.obj 檔案),該檔案稍後可以作為使用 -pack 建構的編譯單元的子模組(具有給定的存取路徑)包含在內。例如,ocamlopt -for-pack P -c A.ml 將產生 a..cmx 和 a.o 檔案,這些檔案稍後可以與 ocamlopt -pack -o P.cmx a.cmx 一起使用。注意:您仍然可以打包一個在沒有 -for-pack 的情況下編譯的模組,但在這種情況下,例外情況將會印出錯誤的名稱。 -g 在編譯和連結時新增偵錯資訊。當程式因未捕捉到的例外情況而終止時,此選項是產生堆疊回溯所必需的(請參閱第 15.2 節)。 -no-g 不記錄偵錯資訊(預設)。 -i 使編譯器在編譯實作檔案(.ml 檔案)時列印所有已定義的名稱(及其推斷的類型或定義)。不產生編譯後的檔案(.cmo 和 .cmi 檔案)。這對於檢查編譯器推斷的類型非常有用。此外,由於輸出遵循介面的語法,它可以協助為檔案撰寫明確的介面(.mli 檔案):只需將編譯器的標準輸出重新導向到 .mli 檔案,並編輯該檔案以移除所有未匯出的名稱宣告。 -I directory 將給定的目錄新增至搜尋已編譯介面檔案(.cmi )、已編譯目標程式碼檔案(.cmx )和函式庫(.cmxa )的目錄清單。依預設,首先會搜尋目前目錄,然後是標準函式庫目錄。使用 -I 新增的目錄會在目前目錄之後搜尋,依它們在命令列上給定的順序搜尋,但在標準函式庫目錄之前搜尋。另請參閱選項 -nostdlib 。如果給定的目錄以 + 開頭,則會將其視為相對於標準函式庫目錄。例如,-I +unix 會將標準函式庫的子目錄 unix 新增至搜尋路徑。
-H directory 其行為與 -I 相同,但 (a) 程式可能不會直接參考以此方式新增至搜尋路徑的模組,以及 (b) 這些目錄會在任何 -I 目錄之後搜尋。這使得能夠為編譯器提供目前程式的傳遞相依性(其相依性的相依性)的已編譯介面和目標程式碼檔案,而不會讓它們悄悄地變成直接相依性。 -impl filename 將檔案 filename 編譯為實作檔案,即使其副檔名不是 .ml 。 -inline n 將內嵌的積極性設定為 n ,其中 n 為正整數。指定 -inline 0 會防止所有函式被內嵌,除非它們的主體小於呼叫位置。因此,內嵌不會導致程式碼大小擴充。預設積極性 -inline 1 允許內嵌稍大的函式,從而導致程式碼大小稍微擴充。較高的 -inline 選項值會導致越來越大的函式成為內嵌的候選者,但可能會導致程式碼大小嚴重增加。 -intf filename 將檔案 filename 編譯為介面檔案,即使其副檔名不是 .mli 。 -intf-suffix string 將以 string 結尾的檔案名稱識別為介面檔案(而非預設的 .mli )。 -labels 標籤在類型中不會被忽略,標籤可以在應用程式中使用,且帶標籤的參數可以按任何順序給定。這是預設設定。 -linkall 強制將函式庫中包含的所有模組連結進來。如果未提供此旗標,則不會連結未參考的模組。當建置函式庫(選項 -a )時,設定 -linkall 選項會強制所有後續連結涉及該函式庫的程式連結函式庫中包含的所有模組。當編譯模組(選項 -c )時,設定 -linkall 選項可確保如果將此模組放入函式庫且連結了該函式庫,則始終會連結此模組。 -linscan 使用線性掃描暫存器配置。使用此配置器進行編譯比使用通常的圖形著色配置器更快,對於長函式和模組來說,速度有時會明顯快很多。另一方面,產生的程式碼可能會稍微慢一些。 -match-context-rows 設定在模式匹配編譯期間用於最佳化的上下文列數。預設值為 32。較低的值會導致更快的編譯速度,但程式碼最佳化程度較低。此進階選項適用於模式匹配繁重的程式導致編譯時間顯著增加的情況。 -no-alias-deps 不記錄模組別名的依賴關係。請參閱第 12.8 節以取得更多資訊。 -no-app-funct 停用函子的應用行為。使用此選項時,每個函子應用都會在其結果中產生新的類型,並且將同一個函子兩次應用於相同參數會產生兩個不相容的結構。 -no-float-const-prop 停用浮點運算的常數傳播。如果程式在其執行期間變更浮點捨入模式,則應給定此選項。 -noassert 不編譯斷言檢查。請注意,特殊形式 assert false 總是會被編譯,因為它是經過特殊類型化的。此標誌在連結已編譯的檔案時無效。 -noautolink 在連結 .cmxa 程式庫時,忽略程式庫中可能包含的 -cclib 和 -ccopt 選項(如果這些選項是在建置程式庫時給定的)。如果程式庫包含 C 程式庫或 C 選項的不正確規格,這可能會很有用;在這種情況下,在連結期間,設定 -noautolink 並在命令列上傳遞正確的 C 程式庫和選項。 -nodynlink 允許編譯器使用僅對靜態連結的程式碼有效的某些最佳化,以產生不可重定位的可執行檔。產生的程式碼不能連結以產生共享程式庫或與位置無關的可執行檔 (PIE)。許多作業系統預設會產生 PIE,這會在連結使用 -nodynlink 編譯的程式碼時導致錯誤。請勿使用 -nodynlink 或在連結時傳遞選項 -ccopt -no-pie 。 -nolabels 忽略類型中非選用的標籤。標籤不能在應用程式中使用,並且參數順序會變得嚴格。 -nostdlib 不要自動將標準程式庫目錄新增至搜尋已編譯介面檔案 (.cmi )、已編譯物件程式碼檔案 (.cmx ) 和程式庫 (.cmxa ) 的目錄清單中。另請參閱選項 -I 。 -o output-file 指定要產生的輸出檔案名稱。對於可執行檔,預設輸出名稱在 Unix 下為 a.out ,在 Windows 下為 camlprog.exe 。如果給定 -a 選項,則指定產生的程式庫名稱。如果給定 -pack 選項,則指定產生的壓縮物件檔案名稱。如果給定 -output-obj 或 -output-complete-obj 選項,則指定產生的物件檔案名稱。如果給定 -shared 選項,則指定產生的外掛程式檔案名稱。 -opaque 當原生編譯器編譯實作時,預設會產生一個 .cmx 檔案,其中包含跨模組最佳化的資訊。它還期望目前編譯的原始碼的相依性存在 .cmx 檔案,並將它們用於最佳化。自 OCaml 4.03 起,如果編譯器無法找到其中一個相依性的 .cmx 檔案,則會發出警告。自 4.04 起提供的 -opaque 選項會停用目前編譯單元的跨模組最佳化資訊。在編譯 .mli 介面時,使用 -opaque 會將編譯的 .cmi 介面標記為,使其後續編譯依賴於它的模組不會依賴於對應的 .cmx 檔案,如果它不存在,也不會發出警告。當原生編譯器編譯 .ml 實作時,使用 -opaque 會產生一個不包含任何跨模組最佳化資訊的 .cmx 。
使用此選項可能會降低產生的程式碼品質,但它會減少編譯時間,無論是在乾淨或增量建置時。實際上,對於原生編譯器,當編譯單元的實作變更時,所有依賴於它的單元可能都需要重新編譯 – 因為跨模組資訊可能已變更。如果實作變更的編譯單元是使用 -opaque 編譯的,則不需要進行此類重新編譯。因此,此選項可用於例如更快地取得編輯-編譯-測試回饋迴圈。
-open Module 在處理介面或實作檔案之前,開啟給定的模組。如果給定多個 -open 選項,則會依序處理它們,就像語句 open! Module1 ;; ... open! ModuleN ;; 新增至每個檔案的頂端一樣。 -output-obj 使連結器產生 C 物件檔案而不是可執行檔。這對於將 OCaml 程式碼包裝為可從任何 C 程式呼叫的 C 程式庫很有用。請參閱第 22 章,第 22.7.5 節。輸出物件檔案的名稱必須使用 -o 選項設定。此選項還可用於產生編譯的共享/動態程式庫(.so 副檔名,在 Windows 下為 .dll )。 -output-complete-obj 與 -output-obj 選項相同,只是產生的物件檔案包含執行階段和自動連結程式庫。 -pack 建置一個物件檔案 (.cmx 和 .o /.obj 檔案) 及其相關聯的已編譯介面 (.cmi ),它會組合命令列上給定的 .cmx 物件檔案,使其顯示為輸出 .cmx 檔案的子模組。輸出 .cmx 檔案的名稱必須使用 -o 選項給定。例如, ocamlopt -pack -o P.cmx A.cmx B.cmx C.cmx
產生已編譯的檔案 P.cmx 、P.o 和 P.cmi ,描述一個具有三個子模組 A 、B 和 C 的編譯單元,對應於物件檔案 A.cmx 、B.cmx 和 C.cmx 的內容。這些內容可以在程式的其餘部分中參照為 P.A 、P.B 和 P.C 。正在組合的 .cmx 物件檔案必須已使用適當的 -for-pack 選項編譯。在上面的範例中,A.cmx 、B.cmx 和 C.cmx 必須已使用 ocamlopt -for-pack P 編譯。
可以透過將 -pack 與 -for-pack 結合來實現多個層級的壓縮。請考量以下範例
ocamlopt -for-pack P.Q -c A.ml
ocamlopt -pack -o Q.cmx -for-pack P A.cmx
ocamlopt -for-pack P -c B.ml
ocamlopt -pack -o P.cmx Q.cmx B.cmx
產生的 P.cmx 物件檔案具有子模組 P.Q 、P.Q.A 和 P.B 。
-pp command 使編譯器將給定的 command 作為每個原始檔的預處理器呼叫。 command 的輸出會重新導向至中繼檔案,然後對其進行編譯。如果沒有編譯錯誤,則稍後會刪除中繼檔案。 -ppx command 在剖析後,透過預處理器 command 傳送抽象語法樹。在第 30 章中描述的模組 Ast_mapper : Ast_mapper 實作了預處理器的外部介面。 -principal 在類型檢查期間檢查資訊路徑,以確保所有類型都以主要方式衍生。使用標籤參數和/或多型方法時,需要此標誌來確保編譯器的未來版本能夠正確推斷類型,即使內部演算法變更也一樣。在 -principal 模式中接受的所有程式也會在預設模式中以等效的類型接受,但二進位簽章不同,這可能會減慢類型檢查速度;然而,在發佈原始碼之前使用一次是一個好主意。 -rectypes 允許在類型檢查期間使用任意遞迴類型。預設情況下,僅支援遞迴透過物件類型的遞迴類型。請注意,一旦您使用此標誌建立介面,您必須再次將它用於所有相依性。 -runtime-variant suffix 將 suffix 字串新增至程式使用的執行階段程式庫的名稱。目前,僅支援一個此類字尾:d ,並且僅當 OCaml 編譯器使用選項 -with-debug-runtime 設定時。此字尾提供執行階段的偵錯版本,這對於偵錯低階程式碼(例如 C 樁)中的指標問題很有用。 -S 保留編譯期間產生的組譯碼。原始檔案 x .ml 的組譯碼會儲存在檔案 x .s 中。 -safe-string 強制 string 和 bytes 類型之間的區隔,從而使字串成為唯讀。這是預設設定,自 OCaml 5.0 起強制執行。 -safer-matching 不使用類型資訊來最佳化模式匹配。即使錯誤地假設模式匹配是詳盡的,這也允許偵測到匹配失敗。這僅影響 GADT 和多型變體編譯。 -save-ir-after pass 在給定的編譯階段之後,將中繼表示儲存到檔案。目前支援的階段和對應的檔案副檔名為:scheduling (.cmir-linear )。此實驗性功能使外部工具能夠使用 compiler-libs 程式庫檢查和操作編譯器的程式中繼表示(請參閱第 30 章和 Compiler_libs )。
-shared 建立一個外掛程式(通常是 .cmxs ),可以使用 Dynlink 模組動態載入。外掛程式的名稱必須使用 -o 選項設定。一個外掛程式可以包含數個 OCaml 模組和函式庫,以及額外的原生物件(.o 、.obj 、.a 、.lib 檔案)。只有在某些作業系統上支援建立原生外掛程式。在某些系統下(目前僅限 Linux AMD 64),連結到外掛程式中的所有 OCaml 程式碼都必須在編譯時沒有使用 -nodynlink 旗標。對於額外原生物件的編譯方式也可能有一些限制(在 Linux AMD 64 下,它們必須僅包含位置無關的程式碼)。 -short-paths 當一個型別在多個模組路徑下可見時,在推斷介面以及錯誤和警告訊息中列印該型別名稱時,使用最短的路徑。以底線 _ 開頭或包含雙底線 __ 的識別符號名稱,在計算長度時會額外加上 10 的懲罰值。 -stop-after pass 在指定的編譯階段後停止編譯。目前支援的階段有:parsing 、typing 、scheduling 、emit 。 -strict-sequence 強制每個序列的左側部分都必須具有 unit 型別。 -strict-formats 拒絕傳統格式實作中接受的無效格式。您應該使用此旗標來偵測並修正這些無效格式,因為它們將在未來的 OCaml 版本中被拒絕。 -unboxed-types 當一個型別可取消裝箱時(即只有一個參數的記錄或只有一個單參數建構子的具體資料型別),除非標記了 [@@ocaml.boxed] ,否則它將會被取消裝箱。 -no-unboxed-types 當一個型別可取消裝箱時,除非標記了 [@@ocaml.unboxed] ,否則它將會被裝箱。這是預設行為。 -unsafe 關閉陣列和字串存取的邊界檢查(v.(i) 和 s.[i] 結構)。使用 -unsafe 編譯的程式速度較快,但不安全:如果程式存取超出其邊界的陣列或字串,可能會發生任何事情。此外,關閉整數除法和模數運算中除數為零的檢查。使用 -unsafe ,整數除法(或模數)除以零可能會使程式停止或繼續執行並產生未指定結果,而不是引發 Division_by_zero 例外。 -unsafe-string 識別 string 和 bytes 型別,使字串可寫入。這是為了與舊的原始程式碼相容,不應在新軟體中使用。從 OCaml 5.0 開始,此選項會無條件引發錯誤。 -v 列印編譯器的版本號碼和標準函式庫目錄的位置,然後結束。 -verbose 在執行所有外部命令之前列印它們,特別是組譯器、C 編譯器和連結器的調用。有助於除錯 C 函式庫問題。 -version 或 -vnum 以簡短形式(例如 3.11.0 )列印編譯器的版本號碼,然後結束。 -w warning-list 啟用、停用或將 warning-list 參數指定的警告標記為致命。每個警告都可以啟用 或停用 ,每個警告都可以是致命 或非致命 的。如果警告被停用,它不會被顯示,也不會以任何方式影響編譯(即使它是致命的)。如果警告被啟用,當原始程式碼觸發時,它會由編譯器正常顯示。如果它被啟用且是致命的,編譯器也會在顯示後停止並產生錯誤。warning-list 參數是一系列警告指定符,它們之間沒有分隔符號。警告指定符是以下其中一種
+ num 啟用警告號碼 num 。 - num 停用警告號碼 num 。 @ num 啟用並將警告號碼 num 標記為致命。 + num1 ..num2 啟用指定範圍內的警告。 - num1 ..num2 停用指定範圍內的警告。 @ num1 ..num2 啟用並將指定範圍內的警告標記為致命。 + letter 啟用對應於 letter 的警告集合。字母可以是大小寫。 - letter 停用對應於 letter 的警告集合。字母可以是大小寫。 @ letter 啟用並將對應於 letter 的警告集合標記為致命。字母可以是大小寫。 uppercase-letter 啟用對應於 uppercase-letter 的警告集合。 lowercase-letter 停用對應於 lowercase-letter 的警告集合。 或者,warning-list 可以使用其助記名稱(如下所示)來指定單個警告,如下所示
+ name 啟用警告 name 。 - name 停用警告 name 。 @ name 啟用並將警告 name 標記為致命。 目前未定義的警告號碼、字母和名稱將被忽略。警告如下(每個號碼後面的名稱指定該警告的助記符)。
1 comment-start 看起來可疑的註解開始標記。 2 comment-not-end 看起來可疑的註解結束標記。 3 已棄用的「deprecated」警示的同義詞。 4 fragile-match 脆弱的模式匹配:即使在匹配的變體型別之一中新增了其他建構子,也仍將保持完整的匹配。 5 ignored-partial-application 部分應用函式:結果具有函式型別且被忽略的運算式。 6 labels-omitted 在函式應用中省略了標籤。 7 method-override 覆寫的方法。 8 partial-match 部分匹配:模式匹配中缺少的情況。 9 missing-record-field-pattern 記錄模式中缺少欄位。 10 non-unit-statement 序列左側的運算式不具有 unit 型別(且不是函式,請參閱警告號碼 5)。 11 redundant-case 模式匹配中的冗餘情況(未使用的匹配情況)。 12 redundant-subpat 模式匹配中的冗餘子模式。 13 instance-variable-override 覆寫的實例變數。 14 illegal-backslash 字串常數中不合法的反斜線跳脫字元。 15 implicit-public-methods 隱式公開的私有方法。 16 unerasable-optional-argument 無法消除的可選參數。 17 undeclared-virtual-method 未宣告的虛擬方法。 18 not-principal 非主要型別。 19 non-principal-labels 沒有主要性的型別。 20 ignored-extra-argument 未使用的函式參數。 21 nonreturning-statement 不返回的陳述式。 22 preprocessor 前處理器警告。 23 useless-record-with 無用的記錄 with 子句。 24 bad-module-name 不正確的模組名稱:原始檔案名稱不是有效的 OCaml 模組名稱。 25 已忽略:現在是警告 8 的一部分。 26 unused-var 可疑的未使用變數:使用 let 或 as 綁定的未使用變數,且不以底線 (_ ) 字元開頭。 27 unused-var-strict 無害的未使用變數:未使用變數,未使用 let 或 as 綁定,且不以底線 (_ ) 字元開頭。 28 wildcard-arg-to-constant-constr 萬用字元模式作為常數建構子的引數給定。 29 eol-in-string 字串常數中未跳脫的行尾符號(不可移植的程式碼)。 30 duplicate-definitions 在兩個相互遞迴的型別中,定義了兩個同名的標籤或建構子。 31 module-linked-twice 同一個可執行檔中連結了兩次模組。 I 已忽略:現在是硬性錯誤(自 5.1 起)。 32 unused-value-declaration 未使用的值宣告。(自 4.00 起) 33 unused-open 未使用的 open 陳述式。(自 4.00 起) 34 unused-type-declaration 未使用的型別宣告。(自 4.00 起) 35 unused-for-index 未使用的 for 迴圈索引。(自 4.00 起) 36 unused-ancestor 未使用的祖先變數。(自 4.00 起) 37 unused-constructor 未使用的建構子。(自 4.00 起) 38 unused-extension 未使用的擴充建構子。(自 4.00 起) 39 unused-rec-flag 未使用的 rec 標誌。(自 4.00 起) 40 name-out-of-scope 建構子或標籤名稱超出範圍使用。(自 4.01 起) 41 ambiguous-name 不明確的建構子或標籤名稱。(自 4.01 起) 42 disambiguated-name 已消除歧義的建構子或標籤名稱 (相容性警告)。(自 4.01 起) 43 nonoptional-label 非可選標籤被當作可選標籤應用。(自 4.01 起) 44 open-shadow-identifier Open 陳述式遮蔽了已定義的識別符。(自 4.01 起) 45 open-shadow-label-constructor Open 陳述式遮蔽了已定義的標籤或建構子。(自 4.01 起) 46 bad-env-variable 環境變數錯誤。(自 4.01 起) 47 attribute-payload 不合法的屬性有效負載。(自 4.02 起) 48 eliminated-optional-arguments 隱式消除可選參數。(自 4.02 起) 49 no-cmi-file 查找模組別名時缺少 cmi 檔案。(自 4.02 起) 50 unexpected-docstring 意外的文件註解。(自 4.03 起) 51 wrong-tailcall-expectation 使用不正確的 @tailcall 屬性註解的函數調用。(自 4.03 起) 52 fragile-literal-pattern (參見 13.5.3 ) 脆弱的常數模式。(自 4.03 起) 53 misplaced-attribute 屬性不能出現在此上下文中。(自 4.03 起) 54 duplicated-attribute 屬性在一個表達式中使用了多次。(自 4.03 起) 55 inlining-impossible 無法內聯。(自 4.03 起) 56 unreachable-case 模式匹配中無法到達的情況 (基於類型資訊)。(自 4.03 起) 57 ambiguous-var-in-pattern-guard (參見 13.5.4 ) 在守衛條件下的不明確的或模式變數。(自 4.03 起) 58 no-cmx-file 缺少 cmx 檔案。(自 4.03 起) 59 flambda-assignment-to-non-mutable-value 賦值給不可變的值。(自 4.03 起) 60 unused-module 未使用的模組宣告。(自 4.04 起) 61 unboxable-type-in-prim-decl 原始宣告中無法裝箱的類型。(自 4.04 起) 62 constraint-on-gadt GADT 類型宣告上的類型約束。(自 4.06 起) 63 erroneous-printed-signature 錯誤的列印簽名。(自 4.08 起) 64 unsafe-array-syntax-without-parsing 搭配使用 -unsafe 與返回語法樹的預處理器。(自 4.08 起) 65 redefining-unit 類型宣告定義了一個新的 '()' 建構子。(自 4.08 起) 66 unused-open-bang 未使用的 open! 陳述式。(自 4.08 起) 67 unused-functor-parameter 未使用的函子參數。(自 4.10 起) 68 match-on-mutable-state-prevent-uncurry 依賴於可變狀態的模式匹配會阻止剩餘參數被取消柯里化。(自 4.12 起) 69 unused-field 未使用的記錄欄位。(自 4.13 起) 70 missing-mli 缺少介面檔案。(自 4.13 起) 71 unused-tmc-attribute 未使用的 @tail_mod_cons 屬性。(自 4.14 起) 72 tmc-breaks-tailcall 尾調用被 @tail_mod_cons 轉換變成了非尾調用。(自 4.14 起) 73 generative-application-expects-unit 生成函子應用於空結構 (struct end) 而不是 ()。(自 5.1 起) A 所有警告 C 警告 1、2。 D 警告 3 的別名。 E 警告 4 的別名。 F 警告 5 的別名。 K 警告 32、33、34、35、36、37、38、39。 L 警告 6 的別名。 M 警告 7 的別名。 P 警告 8 的別名。 R 警告 9 的別名。 S 警告 10 的別名。 U 警告 11、12。 V 警告 13 的別名。 X 警告 14、15、16、17、18、19、20、21、22、23、24、30。 Y 警告 26 的別名。 Z 警告 27 的別名。 預設設定為 -w +a-4-6-7-9-27-29-32..42-44-45-48-50-60 。它由 ocamlopt -help 顯示。請注意,警告 5 和 10 並非總是觸發,這取決於類型檢查器的內部機制。
-warn-error 警告列表 將參數 警告列表 中指定的警告標記為致命。當發出這些警告之一時,編譯器將停止並顯示錯誤。警告列表 的含義與 -w 選項相同:+ 號(或大寫字母)將對應的警告標記為致命,- 號(或小寫字母)將它們變回非致命警告,而 @ 號則同時啟用並將對應的警告標記為致命。注意:不建議在生產程式碼中使用警告集(即字母)作為 -warn-error 的參數,因為當未來版本的 OCaml 新增一些新警告時,可能會中斷您的建置。
預設設定為 -warn-error -a (沒有警告是致命的)。
-warn-help 顯示所有可用警告號碼的描述。 -where 列印標準程式庫的位置,然後退出。 -with-runtime 在產生的程式中包含執行階段系統。這是預設值。 -without-runtime 編譯器不包含執行階段系統(也不包含對它的引用)在產生的程式中;必須單獨提供。 - 檔案 將 檔案 作為檔案名稱處理,即使它以連字符號 (- ) 字元開頭。 -help 或 --help 顯示簡短的使用摘要並退出。
針對 64 位元 x86 架構的選項
針對 Intel/AMD x86 處理器的 64 位元程式碼產生器(amd64 架構)支援以下額外選項
-fPIC 產生與位置無關的機器程式碼。這是預設值。 -fno-PIC 產生與位置相關的機器程式碼。
命令列選項的上下文控制
可以使用以下機制「從外部」修改編譯器命令列。這些是實驗性的,可能會變更。它們應僅用於實驗和開發工作,而不應在發布的套件中使用。
OCAMLPARAM (環境變數) 一組將插入到命令列參數之前或之後的參數。參數以逗號分隔的 name=value 對列表指定。_ 用於指定命令列參數的位置,例如 a=x,_,b=y 表示 a=x 應在解析參數之前執行,而 b=y 應在之後執行。最後,可以在字串的第一個字元中指定一個替代分隔符,該字元位於集合 :|; , 中。 ocaml_compiler_internal_params (stdlib 目錄中的檔案)檔案名稱到將新增到命令列(和 OCAMLPARAM )參數的參數列表的對應。
3 常見錯誤
錯誤訊息幾乎與 ocamlc 的錯誤訊息相同。請參閱第 13.4 節。
4 執行 ocamlopt 產生的可執行檔
ocamlopt 產生的可執行檔是原生的、獨立的可執行檔案,可以直接調用。它們不依賴於 ocamlrun 位元組碼執行階段系統,也不依賴於動態載入的 C/OCaml stub 程式庫。
在執行 ocamlopt 產生的可執行檔期間,也會查詢以下環境變數
OCAMLRUNPARAM 用法與 ocamlrun 中相同(請參閱第 15.2 節),只是選項 l 會被忽略(改為使用作業系統的堆疊大小限制)。 CAMLRUNPARAM 如果在環境中找不到 OCAMLRUNPARAM ,則將改為使用 CAMLRUNPARAM 。如果找不到 CAMLRUNPARAM ,則將使用預設值。
5 與位元組碼編譯器的相容性
本節列出了位元組碼編譯器和原生程式碼編譯器之間已知的 不相容之處。除了這些點之外,兩個編譯器應該產生行為相同的程式碼。
僅當程式在堆積中執行分配時才會偵測到訊號。也就是說,如果在一段不分配的程式碼中傳遞訊號,則直到下一次堆積分配才會呼叫其處理常式。 在 ARM 和 PowerPC 處理器(32 位元和 64 位元)上,可以為浮點數乘法後接浮點數加法或減法(如 x *. y +. z )產生融合乘加(FMA)指令。 FMA 指令避免了對中間結果 x *. y 進行捨入,這通常是有益的,但會產生與位元組碼直譯器產生的結果略有不同的浮點數結果。 原生碼編譯器會執行許多位元組碼編譯器不執行的最佳化,尤其是在 Flambda 最佳化器啟用的情況下。特別是,原生碼編譯器會識別並消除「無效程式碼」,即對程式結果沒有貢獻的計算。例如, let _ = ignore M.f
當編譯為位元組碼時,包含對編譯單元 M 的參考。此參考會強制連結 M 並執行其初始化程式碼。原生碼編譯器會消除對 M 的參考,因此編譯單元 M 可能不會被連結和執行。一種解決方法是使用 -linkall 旗標編譯 M ,使其始終被連結和執行,即使沒有被參考。另請參閱 Sys 標準程式庫模組中的 Sys.opaque_identity 函式。 在 4.10 版本之前,堆疊溢位(通常由過深的遞迴引起)並不總是像使用位元組碼編譯器那樣轉換為 Stack_overflow 例外。運行時系統會盡力捕捉堆疊溢位並引發 Stack_overflow 例外,但有時會失敗,並出現「區段錯誤」或其他系統錯誤。
Copyright © 2024 法國國家資訊與自動化研究所