sql/sql_yacc.cc 編譯階段運行數小時無進展,CPU 佔用低,內存佔用極高。Internal compiler error: program cc1plus got fatal signal 11 / Out of virtual memory / virtual memory exhausted。sql_yacc.cc 是由 Bison 從 sql_yacc.yy 生成的 C++ 解析器代碼,包含極其龐大的 switch-case 狀態機、大量內聯函數、模板實例化。GCC 編譯此文件時:
-finline-functions、-O2 優化,嘗試內聯海量函數 → 符號表爆炸、內存指數增長。
./configure --with-low-memory
# 或
CXXFLAGS="-fno-inline -O0" ./configure
make
--with-low-memory 自動注入 -fno-inline (GCC) 或 -O0 (其他編譯器),禁用內聯、關閉優化,劇減編譯內存峰值。
cd /usr/ports/databases/mysql80-server # 或 mysql57-server 等
make config # 選擇所需選項
make install clean
Makefile 內建 -O0 / -fno-inline 補丁針對 sql_yacc.cc。libtool、cmake、openssl 等)、編譯參數優化、啟動腳本、日誌輪轉。
# 臨時增加 4GB Swap
dd if=/dev/zero of=/swapfile bs=1M count=4096
mkswap /swapfile
swapon /swapfile
# 編譯完成後可關閉
swapoff /swapfile
rm /swapfile
# /usr/ports/databases/mysql80-server/Makefile 片段
.if ${COMPILER_TYPE} == clang || ${COMPILER_TYPE} == gcc
CXXFLAGS+= -fno-inline-functions
.endif
# 針對 sql_yacc.cc 的特殊處理
post-patch:
@${REINPLACE_CMD} -e 's|-O2|-O0|' ${WRKSRC}/sql/CMakeLists.txt
libtool 依賴:libtool 是 GNU 構建系統膠水層,統一共享庫構建接口,Ports 自動拉取構建依賴,非運行時依賴。pkg install mysql80-server 直接拿預編譯二進制包,完全跳過編譯,最省時。sql_yacc.cc 編譯通常無需特殊參數即可通過。CXXFLAGS="-fno-inline" make 即可。make -j$(nproc) 全速並行編譯 → 內存峰值 × 核心數,必發 OOM。編譯 sql_yacc.cc 時建議單線程:make -j1 sql/sql_yacc.cc.obj 再 make -j$(nproc)。--with-low-memory 文檔提示 → 浪費數小時等待失敗。CMakeLists.txt / Makefile 硬編碼參數 → 升級時遺失,Ports 機制失效。pkg install 或 portmaster databases/mysql80-server,除非需要極度定制編譯選項。FreeBSD 編譯 MySQL 卡在 sql_yacc.cc 是經典的「編譯器內存爆炸」案例。**理解根因 (Bison 生成代碼特性 + GCC 內聯優化),應用官方 --with-low-memory 或 Ports 內建優化,能將編譯時間從「不可接受」壓縮到「喝杯咖啡的功夫」**。現代 FreeBSD + Clang 環境下該問題已大幅緩解,但掌握排查思路對所有大型 C++ 專案編譯優化皆有裨益。