TW Community

Compiler Explorer 介紹

如果突然想要測試想法,簡單地寫出來驗證,手邊沒有可以編譯執行的工具,或者想要測試很多版編譯器,可以試試看 Compiler Explorer

https://github.com/compiler-explorer/compiler-explorer
Compiler Explorer is an interactive compiler exploration website. Edit C, C++, Rust, Go, D, Haskell, Swift, Pascal, ispc or other language code, and see how that code looks after being compiled in real time. Multiple compilers are supported, many different tools and visualations are available, and the UI layout is configurable

簡單來說它可以讓你在上面測試 C/C++, Rust 等或甚至 CUDA,並編譯出來且某些還可以執行檢查結果。另外他也提供很多種編譯器版本,只要選單一按就可以切換過去。

介面介紹(每個人進來的版面可能會稍微不一樣)

三個主要界面

interface introduction
  • A: 寫程式碼的地方
  • B: 編譯結果 Assembly (組語?)
  • C: 執行結果或者編譯錯誤訊息

一些選項

  1. 可以新增編譯器或者執行結果,也可以新增額外撰寫程式碼的地方
  2. 選擇程式語言 C++/Python/CUDA 等
  3. 編譯器,會根據 2 所選的改變。像 C++ 就會有 gcc/clang 各版本;CUDA 就是 nvcc/clang。
  4. 編譯器參數
  5. 可以將目前寫的東西分享給別人,例如本文章的程式網址也是從這裡出來
  6. 主要是有一個 Executor from this 他就會跑出 C 的視窗,它的結果就是從這個編譯器出來;而上面 1 提到的執行結果 Execution Only ,會新增一個 B+C 但沒有 Assembly。

另外也可以注意到:Compiler Explorer 會將 Assembly 跟程式碼相對應的地方用相同的顏色標註起來,這樣如果是一些編譯期間的結果,就也可以從這邊去確認。

範例介紹: throw in constexpr function (https://godbolt.org/z/6sTqqvrrT)
註: constexpr function 會根據輸入,作為 constexpr 或者一般函數來使用,當作為 constexpr 會在編譯期間決定結果。

#include <stdexcept>
constexpr bool test(int value) {
    if (value < -20) {
        throw std::runtime_error("value < -20");
    }  
    return value > 0;
}
int main () {
    constexpr auto correct = test(-1);
    auto runtime_error = test(-25);
    // constexpr auto error = test(-25);
    return 0;
}
example code

如果當整個是 constexpr 又遇到 value < -20,編譯器應該要無法編譯;當普通使用的時候,value < -20 會丟出 runtime_error。編譯選項只用 -std=c++14

runtime error (expected)

可以看到右上方編譯結果,以及右下方的執行結果,執行時的確會正常丟出 runtime_error。那當我們把第 11 行加進去呢,可以看到目前是可以在編譯時跳出錯誤。

compile time error (expected)

但是當我們要將此功能加入到其他專案的話,就要額外考慮專案目前所使用的編譯器版本是不是都可以成功運行,例如 ubuntu 16.04/18.04/20.04 一開始就有的編譯器版本可能就常會在支援的列表中。

我們可以在 Compiler Explorer 很輕鬆地去更換編譯器,去檢查是不是有些編譯器無法照所想的運行。

像這個程式,當我們試到 gcc 6 以上都可以像我們所預期的一樣, constexpr 會在編譯期間檢查,其他的則會在執行期間檢查。但當試到 gcc 5.x 就會發現即使第 9 行 constexpr auto correct = test(-1) 是正確的,但編譯還是會失敗。而 gcc 5.4 又是 ubuntu 16.04 所預設的編譯器之一。考量到這些點,專案本上就要決定不要加入這個方式去檢查,或者更動專案本身所支援的編譯器版本。

gcc 5.4 error

其實一開始在測試這個功能並沒有去檢查到 gcc 5.x 版,直到發現這一篇 https://stackoverflow.com/questions/34280729/throw-in-constexpr-function 裡面提到 gcc 5.3 是不能用的,另外再另一篇 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67371 裡頭也有提到 8.0 和 8.3 都失敗 (雖然在 Compiler Explorer 試沒有問題) ,所以才在這邊測試。


CUDA 簡單範例,將前面的 2 改成 CUDA 就可以在 3 選擇 nvcc 來編譯看看了,以下圖片就是當第一次選到 CUDA 會跳出的範例。那在這裡執行視窗只會有編譯的錯誤訊息而沒有實際執行的結果。

cuda example

我個人常常會用 Compiler Explorer 做一些簡單的測試,也不用去擔心編譯器切換的問題或者需要找地方建立檔案,而且也很方便給別人目前的結果,對方也可以自己增減東西在上面 (只有單方面更改,非線上合作)