嗷嗷嗷!!!好激動,我好蠢。不過最后還是解決了。嗚嗚嗚
有些都是東一塊西一塊查的,如果有侵權歡迎私信我,我注明出處。
一 gcov&CMake
昨天試了下測試代碼和被測代碼都是c++的情況,直接編譯生成gcno文件,再一運行,生成gcda文件。腳本統計,blingbling生成了報表,簡直漂亮!
不過我們的工程比較大= =。編譯時也需要很多依賴文件。
因此使用場景為:在機器A目錄編譯,拷貝純bin文件到B目錄上運行。編譯方式為CMake
1 修改編譯腳本
- 找到CMakeList.txt文件,添加如下內容:
-
# coverage option OPTION (ENABLE_COVERAGE "Use gcov" OFF) MESSAGE(STATUS ENABLE_COVERAGE=${ENABLE_COVERAGE}) IF(ENABLE_COVERAGE) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
# 其中 -fprofile-arcs 用來生成 gcno 文件; -ftest-coverage 用來在統計時生成 gcda 文件# SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") ENDIF()
- 編譯時使用命令如下:
cmake -DENABLE_COVERAGE=ON ..
- 編譯后查看文件目錄:build一路向下
-
******/build/CMakeFiles/ad_server.dir/src $ll -rw-rw-r-- 1 mobdev mobdev 1431748 Jun 22 18:24 A.cpp.gcno -rw-rw-r-- 1 mobdev mobdev 2138256 Jun 22 18:24 A.cpp.o -rw-rw-r-- 1 mobdev mobdev 314180 Jun 22 18:25 B.cpp.gcno -rw-rw-r-- 1 mobdev mobdev 871944 Jun 22 18:25 B.cpp.o -rw-rw-r-- 1 mobdev mobdev 2053332 Jun 22 18:25 C.cpp.gcno -rw-rw-r-- 1 mobdev mobdev 3931584 Jun 22 18:25 C.cpp.o -rw-rw-r-- 1 mobdev mobdev 1063036 Jun 22 18:24 D.cpp.gcno -rw-rw-r-- 1 mobdev mobdev 3280472 Jun 22 18:24 D.cpp.o
- 如上表示編譯成功
2 拷貝bin文件到目錄B,注意保持目錄B與目錄A的為同一次編譯結果(我是檢查md5文件)
如果是從機器A到機器B,注意配置gcov_prefix交叉編譯。
3 啟動你的服務,按原方式執行測試用例。case執行完成后進入下一步
4 生成gcda文件。vim test.sh,內容如下:
-
#!/bin/sh SERVER_NAME=$1 pid=`ps -ef | grep $SERVER_NAME | grep -v "grep" | awk '{print $2}'` echo $pid gdb -q attach $pid <<__EOF__ p __gcov_flush() __EOF__
執行命令:sh test.sh your_servername
5 檢查:因為這次我的編譯和測試在同台機器的不同目錄,因為gcda文件會生成到編譯時的gcno同目錄,檢查其中已有gcda文件。如下:
-
******/build/CMakeFiles/ad_server.dir/src $ll -rw-rw-r-- 1 mobdev mobdev 71772 Jun 22 18:55 A.cpp.gcda -rw-rw-r-- 1 mobdev mobdev 1431748 Jun 22 18:24 A.cpp.gcno -rw-rw-r-- 1 mobdev mobdev 2138256 Jun 22 18:24 A.cpp.o -rw-rw-r-- 1 mobdev mobdev 18452 Jun 22 18:55 B.cpp.gcda -rw-rw-r-- 1 mobdev mobdev 314180 Jun 22 18:25 B.cpp.gcno -rw-rw-r-- 1 mobdev mobdev 871944 Jun 22 18:25 B.cpp.o
二 生成html頁面
進入gcda和gcno文件所在目錄,執行 lcov -c -o result.info -b . -d . //生成info文件 genhtml result.info -o Report //生成html文件 tar cvf Report.tar.gz Report //壓縮文件 sz Report.tar.gz //下載到windows系統 解壓打開其中的index.html即可看到測試代碼覆蓋率
三 生成xml報告
1 安裝gcovr
cd /usr/local wget https://github.com/gcovr/gcovr/archive/3.2.tar.gz tar -xvf 3.2.tar.gz cd gcovr-3.2/scripts cp gcovr /usr/bin
2 在編譯路徑下執行 gcovr -r .即可查看覆蓋率情況
3 為了使其生成Cobertura可用的xml文件,可以使用命令
gcovr -r . --output yourdir/coverage.xml -xml-pretty
vim coverage.xml即可看到xml報告
四 問題
1 描述:無法生成gcda文件
原因如下:
- 用戶代碼調用 exit 正常結束時,gcov_exit 函數得到調用,其繼續調用 __gcov_flush 函數輸出統計數據到 *.gcda 文件中
- 若用戶進程並非調用 exit 正常退出,覆蓋率統計數據就無法輸出,也就無從生成報告了。后台服務程序若非專門設計,一旦啟動就很少主動退出,用 kill 殺死進程強制退出時就不會調用 exit,因此沒有覆蓋率統計結果產生。
解決:執行(一)4步驟即可。
2 描述:無法組合gcda和gcno文件:"stamp mismatch with notes file"
原因如下:
- 網上找了好多答案,說是編譯版本不一致,導致時間戳不一致,我一直沒有理解。
- 確認自己這兒是因為生成gcno文件的編譯版本和生成gcda文件的版本不一致。
-
我的操作: 1 編譯二進制文件ad.server,生成了gcno文件 2 拷貝ad.server進測試環境,測試生成了gcda 3 中途又編譯了一次ad.server,生成了新的gcno文件. 即gcno和gcda文件使用的ad.server並不是同一次編譯的結果。 最后通過對比兩個地方的ad.server的md5發現了不同,我好蠢= =
解決:解決很簡單,確保你的版本就ok了,可以對比二進制文件的md5.
查看時間戳:hexdump -e '"%x\n"' -s8 -n4 A.cpp.gcno 可以看到時間戳。
hexdump -e '"%x\n"' -s8 -n4 A.cpp.gcda 可以看到時間戳
3 描述:想要讓gcda文件生成在指定目錄
場景:有時候是在機器A編譯,機器B運行,這種情況就會不能生成gcda文件,提示找不到目錄
解決:gcov的交叉編譯
操作如下:
- vim /etc/profile 進行配置
-
export GCOV_PREFIX="/data/ad_server/ad_server.dir" //gcda的目標路徑 export GCOV_PREFIX_STRIP=9 //向上數你的路徑到需要配置的那個 比如我的編譯路徑是/data/code/adserver/6/5/4/3/2/*.gcno,我就設置了9,應該也可以設置export GCOV_PREFIX_STRIP=999等很大然后配置全路徑,我沒試
- source /etc/profile 使其生效
- 重啟服務進程
- 執行測試代碼,exit()退出,查看profile的設置路徑,已經有gcda文件
- 拷貝gcno文件到gcda路徑,統計代碼覆蓋率
- blingbling的就大功告成了!
我的問題:配置了n久該路徑一直不生效,最后要哭了。今天偶然發現需要重啟進程,憂傷極了
4 描述:無法使用gcovr生成覆蓋率--得到的覆蓋率為0%
$gcovr -r . ------------------------------------------------------------------------------ GCC Code Coverage Report Directory: . ------------------------------------------------------------------------------ File Lines Exec Cover Missing ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ TOTAL 0 0 --% ------------------------------------------------------------------------------
解決:執行gcovr -r .在編譯的大路徑下即可,或者在執行時指定source 路徑 如 gcovr -r /home/test/mytest/XXXX/
目錄不對,只有gcda和gcno、cpp.o文件無法生成覆蓋率,需要源碼--猜測
5 描述:使用 --remove 后未在指定路徑看到 -o 后的新的 info 文件
解決:實際生成了,使用命令 find / -name "new_file.info" 發現在根目錄下,不知道為什么會這樣,使用時更新為 指定絕對路徑 就 ok 了