2014年11月4日 星期二

用python 產生未引入檔的報表

故事是這樣子的,最近我無聊的時候玩玩的專案
qucs 理想上這個project是要達成類似ADS的模擬軟體,很不幸的在功能上遠遠不足;project 開始的年代是2003年左右,當初應該是qt3 寫的,因為qt 支援不足那時候他們還自己寫qt 物件vtabbar, vtabbeddockwidget什麼的。
現在還有一堆qt3support的東西沒有清除乾淨,這整團又黏得死死得要一口氣清光,原作者去年有設法把它拿掉,弄了50多個提交之後沒什麼結果,物件繼承又弄得一團糟,十年累積下來的修改可以氣死人。

從一開始參與的時候,我就覺得這個project 很怪,怪在哪呢?無論是把Qt3拿掉升去Qt4,幫它加上新功能等等,不管你怎麼改,改了多少Qt的object進去,它編譯通常都會過,就算你沒include,它還是過了……
後來我才檢視到,在它最上層,位階僅次於main.h的qucs.h(光看名字就知道這有多核心XDD)裡,竟然加上了一行
#include <QtGui>
這…這行也真是霸氣外露,這根本是幫project加了個金剛不壞之身,之後所有的header files應該把qt object 的include都投去太平洋才是;這實在不是好習慣,QtGui 包含了太多的標頭定義,一方面會影響到編譯時間(下面連結有人說40%),同時也讓你抓不到每個檔案到底需要哪些標頭。

後來我用grep 下去掃一下,總共有兩個重要標頭檔被加上QtGui include,五個子資料夾d 重要標頭檔被加上這行,另外還有113個原始碼檔案。
如果要手動慢慢移除,大概會花上不少時間;也可以用sed 一個氣全移光,再來慢慢修,不管怎麼樣,移掉它們一定會產生一堆沒include標頭檔產生的 undefined error,要慢慢把該include 的檔案加上去。
老話一句:「working hard, after you know you are working smart」

為了這個問題,寫一個python code來解決。
問題很簡單:一但移除include QtGui,編譯時會產生一堆undefined error,我們要把該引入的標頭檔加上去,我的策略很簡單,用一個python script去剖析編譯的錯誤訊息,找去哪個檔案缺什麼定義,自動寫入暫存檔裡,產生該加上的include code即可。

呼叫make的地方就用python 的subprocess 模組,用make -k儘量產生各種錯誤:
from subprocess import Popen, PIPE
cmd = ['make', '-k', '-j8']
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
stdout, stderr = p.communicate()
errormsg = str(stderr)
這樣我們就取到錯誤訊息了,stdout其實可以不理它。

這個project用的是clang,它的message 形式是這樣:
檔名:行數:字元數: error: unknown type name '物件名'
該行的原始碼
可能的錯誤訊息有unknown type name跟implicit instantiation of undefined template。

要剖析也很簡單,連regular expression都不用,用split直接切下來就是了,最後我們用字典建立檔案跟缺少的物件列表:
files = {} filename = line.split(':')[0]
classname = line.split(“'”)[1]
if filename in files:
    if classname not in files[filename]:
        files[filename].append(classname)
    else:
        files[filename] = []
        files[filename].append(classname)
這樣我們有報表了,再來就是產生一下引入的原始碼,如果是標頭檔,會產生class forward declaration跟include引入,原始碼檔就比較簡單,全部產生引入即可,如此一來就能輕鬆產生引入的程式碼。最後我們還能用subprocess幫我們打開vim,把有錯的檔案跟我們寫入的報表一起打開,就能輕鬆修正所有的錯誤。

結果:
我花了大約30分鐘的時間,把120個檔案的QtGui 引入全部刪完了,單核心編譯時間從原本的344秒加速到245秒,真的大約提速29 % OAO

相關資料:
1. Qucs 專案:
https://github.com/Qucs/qucs
2. QtGui相關討論:
http://qt-project.org/forums/viewthread/18766

沒有留言:

張貼留言