御用 C++ 構建之編譯規范

jopen 8年前發布 | 9K 次閱讀 C/C++開發 C/C++

在開發程序中,我突然對 C++ 的編譯選項產生了興趣,這方面也大有規范可立。于是搜索到的第一結果是 Hacker News 上的 What Are Your GCC Flags? 還有個變本加厲的 How to turn on (literally) ALL of GCC’s warnings? 以及 Flags to enable thorough and verbose g++ warnings .

然后我又跑去 各大熱門 C++ 項目 扒 flags. 出乎意料,leveldb 這種重量級 Google 項目的編譯選項都很簡單。無非全是 -Wall -Wextra -O2 之類的。但我還發現,它們幾乎都用 CMake 來構建,于是我便投入精力學習了 CMake 一番。

調研還挺辛苦,總之從此 御用編譯器是 GCC , Clang 似乎也不賴,但目前還在觀望; 御用構建系統是 CMake , StarBrilliant 如此評價它:「又玄學又難用,但沒有更好的代替品了。」;我還在熟悉 CMake 中, 所以只總結了御用 C++ 構建之編譯規范,即 CMAKE_CXX_FLAGS 如下 :

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_FLAGS "-Wall -Wextra")
set(CMAKE_BUILD_TYPE "RelWithDbgInfo")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -O0 -g -ggdb -DDEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} -O2")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS} -Og")

CMAKE_CXX_STANDARD 指定 C++14, 我先進我自豪!

CMAKE_BUILD_TYPE 默認指定 RelWithDbgInfo 編譯類型 ,即 CMAKE_CXX_FLAGS_RELWITHDEBINFO , 同時也是日常開發的編譯類型; 且 -Og 會盡量開啟不影響 debug 的優化,即接近 -O2 選項, 所以這類型在 profile, debug, develop, optimize 上都取得了很好的平衡點。 如果是開源項目的話,開發者還可以一時高興,直接用這編譯類型發布算了。若下游的打包者不想要 debug info, 也可以自行 strip 掉。

CMAKE_CXX_FLAGS_DEBUG 專門 debug 用 ,特點是禁用優化,可以 debug 宏,額外編譯 DEBUG 宏(Caffe 就用來輸出調試信息)。雖然 御用編程規范本身就禁用宏 ,不過我發現 DEBUG 宏可能是例外 ,用好了對 debug 很有幫助,而且這編譯選項也就只在 debug 時用,大家知道這點就好。

CMAKE_CXX_FLAGS_RELEASE 當然專門發布 release 版了 。事實上,在 CMake 時可以在命令行選項指定該編譯類型: cmake -CMAKE_BUILD_TYPE=Release (<path-to-source> | <path-to-existing-build>) .

事實上,還有一大堆有用的 flags 我還沒放進 CMAKE_CXX_FLAGS_RELWITHDEBINFO , 具體作用還請自查 man gcc :

-funroll-loops -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wno-invalid-offsetof -Wmissing-declarations -Wmissing-include-dirs -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-compare -Wsign-conversion -Wsigin-promo -Wstrict-null-sentinel -Wswitch-default -Wswitch-enum -pendantic -Wredundant-decls -Wconversion -Weffec++ -Wnon-virtual-dtor -Wconversion -Wwrite-strings

畢竟多多益善,而且我還要再補充最后一個終極 flag: -Werror ! 把所有警告轉化為錯誤,從而強制 C++ 工程師完美無瑕之零警告 ,也應了 Effective C++ 第五十三條款「不要輕忽編譯器的警告」。 但這些 flags 恐怕難以在組織推廣Linus 先生對此開地圖炮過 ,我對此深有同感。

此外我和 felixonmars 討論了 Arch Linux 發行版打包的編譯選項,對話如下:

Isaac Ge: @felixonmars 你們打包 C/C++ 在會調 GCC_FLAGS 還是直接用開發者的設置?

[felixonmars] acgtyrant: 會盡量調整成我們的要求,有些默認差不多的其實也沒管

[felixonmars] 默認開 native、禁用安全策略等嚴重問題是主要的調整目標

[felixonmars] 小問題可能我們都沒發現……

[felixonmars] 我今天 rebuild 了手上的全部 go 包,啟用了安全策略

[felixonmars] 另外還有 –as-needed,是最近一段時間開始重視的

[felixonmars] 鏈接了一大堆不相干庫的,我們會嘗試強行加 –as-needed

Isaac Ge: 安全策略?第一次聽說Isaac Ge: @felixonmars 有公開的明文規范嗎?

[felixonmars] 比如 -fstack-protector-strong –param=ssp-buffer-size=4

Kasei Wang: gcc防溢出的那幾個選項么

[felixonmars] 這種就算安全策略

Kasei Wang: 哦那個我自己開著

[felixonmars] acgtyrant: 可以安裝 checksec 查看

[felixonmars] 類似這樣用:checksec –file /usr/bin/ls

[felixonmars] 我們的目標是全發行版全綠(

[felixonmars] 現在因為 PIE 支持不科學,暫時沒考慮 PIE 那一項

[felixonmars] 目前我們的 CFLAGS 默認會做到除 PIE 以外只有 RELRO 是黃的,其他全綠

[felixonmars] 所有沒有達到這個效果的,都是應該修的

Written with StackEdit .

來自: http://tech.acgtyrant.com/御用-C-構建之編譯規范/

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!