2013年8月8日 星期四

使用gnu make編譯Qt 專案

最近白天跑EM,夜深寫QT。

當然這完全沒什麼,其他同學至少兩年前就寫過了LOL。

只能說Qt 真是相當強大的工具,最基本的signal & slot的概念,如果對GTK的callback熟悉的話,很快就能上手。
一般在寫Qt時,最常用的還是用qmake來產生Makefile,畢竟qmake寫得還不賴,打一次就會產生好Makefile,接著make即可;不過有時個人習慣還是偏好用gnu-make,可以自己編寫Makefile,做一些細部的調整,用qmake的話只要重新產生一次Makefile,這些細部調整就要重新再修改一次。
這篇就是說明一下,要如何使用gnu-make來處理Qt專案。

--

基本上Qt的運作原理,是對原有的C++進行擴展,然後透過Qt提供的解析程式,產生額外的原始碼檔,少了這些額外的原始碼,在編譯的時候會產生一堆可怕的錯誤資訊,要用gnu-make編譯Qt專案,其實只要呼叫這些解析程式來產生原始碼即可;總共會用到的程式有三個:moc, rcc, uic;分別作用是:產生meta object(故名Meta-Object Compiler)、處理resource(resource compiler)檔、產生介面檔(User Interface Compiler)。

一般Makefile裡面會有這些東西,用來把所有的source轉換成object file。
SOURCE_FILE = main.cpp 
OBJECT_FILE += $(addsuffix .o, $(basename $(SOURCE_FILE)))

為了Qt,我們加上下列的變數定義:
#==================================================
# Qt special function
#==================================================
QT_LIBS = -lQtCore -lQtGui -lQtOpenGL
QT_PATH = /usr/lib/qt4/bin
QT_MOCFILE = mainwindow.h
QT_RCCFILE = resource.qrc
QT_UICFILE = first.ui
QT_MOCSOURCE = $(addprefix moc_, $(addsuffix .cpp, $(basename $(QT_MOCFILE))))
QT_RCCSOURCE = $(addprefix qrc_, $(addsuffix .cpp, $(basename $(QT_RCCFILE))))
QT_UICSOURCE = $(addprefix ui_, $(addsuffix .h, $(basename $(QT_UICFILE))))

這一整個區塊與QT有關,所有參數都加上QT為標示。
QT_PATH設定Qt的執行檔位置,如果安裝在其他地方、或要用其他版本就要自己換地方。
QT_*FILE是先定義,moc, rcc, uic分別要處理的檔案,moc會處理所有.h檔,產生含meta object的cpp檔;rcc會處理qrc file,產生相對應的cpp檔;uic則會處理ui,產生可包入的header file。
透過makefile的suffix, prefix,轉成我們需要轉出的檔案名稱,個人的習慣是在這些檔名前加上關鍵字moc_, qrc_, ui_。

--

接著是利用implicit rules來compile所有的物件檔:
TARGET = program
BIN_DIR = bin
LIBRARY_DIR = library
SOURCE_FILE = main.cpp $(QT_MOCSOURCE) $(QT_RCCSOURCE)
OBJECT_FILE += $(addsuffix .o, $(basename $(SOURCE_FILE)))

由於moc和rcc會產生新的cpp檔,因此需要將它們列入;然後就可以用implicit rules執行:

%.o:%.c
  $(CC) -c lt; -o $@ $(CFLAGS) $(INCLUDE)
  @$(MOVE) $@ $(LIBRARY_DIR)

%.o:%.cpp
  $(CXX) -c lt; -o $@ $(CXXFLAGS) $(INCLUDE)
  @$(MOVE) $@ $(LIBRARY_DIR)

moc_%.cpp: %.h 
  $(QT_PATH)moc $(DEFINES) $(INCLUDE) lt; -o $@

qrc_%.cpp: %.qrc
  $(QT_PATH)rcc lt; -o $@

ui_%.h: %.ui
  $(QT_PATH)uic lt; -o $@
前兩項是將c/cpp-編成 .o檔,當遇到QT_MOCSOURCE, QT_RCCSOURCE的檔案,就會由moc, rcc產生。
另外在編譯主程式的相依性中,原本我們只要它編譯所有的OBJECT_FILE,現在還要加上由uic產生的header file:
$(TARGET): $(OBJECT_FILE) $(QT_UICSOURCE)
  cd $(LIBRARY_DIR); \
  $(LINKER) -o $@ $(OBJECT_FILE) $(LIBS); \
  cd ..
  mv $(LIBRARY_DIR)/$@ $(BIN_DIR)
如此一來,就會觸發uic產生出header file。

--

透過以上的設定,即可完成Qt專案的編譯,不過最後還是要說,雖然我這裡是這麼寫,但其實真的用的時候還是用qmake來產生Makefile =w=,套句AZ大神的話「它寫得這麼好幹嘛不用?你白痴嗎。」

結論:這篇網誌是一篇垃圾,寫Qt請愛用qmake。 lol

參考資料:
1. C++ GUI Programming with Qt 4
2. http://woboq.com/blog/how-qt-signals-slots-work.html

2013年8月1日 星期四

你會拒絕政府的好意嗎?

最近許多事情佔據了新聞版面:國軍虐死案、大埔拆屋案,然後是一些媒體刻意掩蓋的台北違法抓人事件,這些都是政府在迫害人民的案例。

--

這其中大埔拆屋案是最有趣的。
儘管劉政鴻牠拆了一堆人的房子,儘管苗栗債務激增,人均負債升到全國第二;關於他只是要炒地補縣庫的證據如此明確,可是他的支持度還是這麼高,甚至天下雜詩民調的滿意度還有68.9%,遠見雜誌的首長大評比,他還是五顆星的縣長。

這是不是怪怪的?
事實上看看遠見雜誌所寫的內文,政鴻縣長的政績,很多都是用錢堆出來的,也導致苗栗縣債台高築。
引用內文:「2008年11月,首次舉辦大型藝文活動,就邀來世界三大男高音卡列拉斯獻唱,免費讓民眾參加音樂饗宴;12月4日至6日三場愛爾蘭《大河之舞》讓民眾目不暇給。2009年3月更加碼舉辦苗栗國際音樂節,邀請情歌王子布萊恩麥肯奈特、鋼琴玩家邁可森與世界三大男高音多明哥演出。」

請到三大男高音而且是免費的活動,這樣要花掉多少錢?(按:我查到是0.021G)還要加上行銷之類的預算,例如在遠見雜誌的廣告,之類。
還別說每年年底的一定要有的跨年晚會跟煙火,你去晚會有付過錢嗎?請歌手的錢是誰出的?

好聽的這叫「執政優勢」,其實就是買票。
我們總認為選舉買票要走到你門前,把裝著錢的信封送你,然後說投某某垃圾;但政府的好意不來這套,它是更隱晦的買票型式,他用活動讓你覺得:這個政府真好,這位首長有在做事,下次也投他吧。明著買票大家會拒絕、會厭惡;暗行的買票,大家會很高興的收下來,連拒絕都不會;最重要的,你會覺得買票者是真有能力,你真的被買了。

那政府的錢從哪來?靠著舉債而來,靠著拆人民的房子炒地皮而來;大家享受免費藝文活動時,就要有人被迫家破人亡;政府宣稱活動產生了多少商機,看清楚,那是政府吸乾一些人的血,用那些血寫出來的。
但…這很弔詭,為了更有效的管理社會,我們創造了政府這個架構,政府不可能不做事,否則就不需要政府了;但政府又不能過度的做事,那樣的好意已經成了壞事;該如何在適當的政策與過度的好意的無限近似漸層上,劃出一條一刀兩斷的界線?我沒有答案。


2014巴西舉辦world cup,人民在網路上呼籲:「非巴西人們,別來world cup」;下一次,當各縣市政府舉辦跨年晚會、發射跨年煙火,將那一小部分被害人民的財產燒盡,化做天上那一瞬的閃光時,你會說:「別去」嗎?

--

參考資料:
  1. 北美智權報:縣市誰先破產?
    http://www.naipo.com/Portals/1/web_tw/Knowledge_Center/Editorial/publish-33.htm
  2. 遠見雜誌:5星滿意度苗栗縣長 劉政鴻:
    http://www.gvm.com.tw/Boardcontent_16177.html
  3. 維基:天下雜誌滿意度調查:
    http://zh.wikipedia.org/wiki/%E5%A4%A9%E4%B8%8B%E9%9B%9C%E8%AA%8C%E7%B8%A3%E5%B8%82%E9%95%B7%E6%96%BD%E6%94%BF%E6%BB%BF%E6%84%8F%E5%BA%A6%E8%AA%BF%E6%9F%A5
  4. Protest against world cup:
    http://metro.co.uk/2013/06/16/brazilians-protest-against-staging-of-dangerous-world-cup-3843409/

2013年7月25日 星期四

Office-Word系列:3.善用交互參照


最近,實驗室的學長們都在寫論文。在譔寫論文時,常需要引入大量的圖片、表格、方程式等,在內文中還需要使用「shown in Fig. 3.10」、「eq 2.10」,這類插入物件與文字間的相互連結。
而當插入新的物件時,如果還需要一頁一頁手動修改內文的文字內容,在大文件上將是相當麻煩的事情,甚至是接近不可能的任務,秉持「work hard, after you know you are working smart」的精神,這種方法是絕對不能接受的。
這裡要介紹的交互參照,可以讓word自行進行文字-物件的連結,加速論文的修改過程。

--

如上所述,交互參照在管理文字與物件間的連結,點開word中的「插入」-「交互參照」或「參考資料」-「交互參照」,可看見可以連結的物件包括:編號項目、標題、書籤、註腳、附註、方程式、表格、圖片八項,以下以圖片進行交互參照使用說明,這個步驟適用於圖片、表格與方程式的參照上。

1.第一步當然是先插入圖片。
2.建立起圖片標號,在「參考資料」-「插入標號」為圖片建立一個標號,標號其實是指標籤與編號,包括下列幾個部分:「標籤.編號.內文」,例如
「Fig.1 Touhou is the best」
這個標籤是最重要的,交互參照認的就是這個標籤,如果你覺得Fig這個標籤不好,也可以在插入標號的選單內自行建立新的標籤。 

3.現在在你想要插入交互參照的地方,點選「交互參照」;參照類型會列出這份文件裡的所有標籤種類,我們上面的標籤是Fig就選Fig;在下面選擇你想要連結的圖片;「插入參照類型的」則視你要插入什麼文字,如果只要插入「Fig.1」就選「標籤與數字」,如果只要Fig那就是「標籤」。
確定之後就會看到文字出現「Fig 1」。

4.會自己加文字完全沒什麼,重要的是,現在我們可以在圖表一之前加入新的圖片,同樣加上圖表標號;此時只要全選文件,右鍵選「更新功能變數」,即可更新所有的交互參照。如下圖所示,內文會自動變成「fig 2」,圖片下方的標號也會自動更新。

有一點要注意的是,一但完成了交互參照,這張圖片便不能輕易刪除,否則參照的文字會變成「找不到參照來源」,這個目前小弟我也只會手動刪除……。

5.建立圖表目錄,針對圖片、表格、方程式,word可以自動生成圖表式目錄,跟製作一般目錄一樣簡單,只要選取「參考資料」->「建立圖表目錄」,下面的標籤選擇你想要製作的標籤即可。

結論:
使用交互參照進行物件與文字間的管理,也許平時寫文件時不太需要用到,但對付文件內容的修改時,善用交互參照就顯得相當有威力。

2013年7月21日 星期日

防止.bashrc輸出內容造成sftp無法使用

目前小弟我負責維護幾台工作站,之前幾台工作站的FTP都無法使用,一定要從另一台工作站傳送,反正利用網路硬碟的功能,其他的工作站還是能拿到檔案。
前幾天工作站因為不明原因死了,非得讓無法用FTP的工作站連FTP;debug才發現原因:

在.bashrc中,放入了許多通知用的訊息,echo內容會讓sftp的收到錯誤訊息直接中止傳輸。
.bashrc的第一行有一行判斷式:
if [ $prompt ]; then echo "blahblahblah" fi
前面if用來擋掉非互動的連線,不過這好像沒什麼用…查一下正確的方法是用:
if [ "$SSH_TTY" ]
這個可以確認使用者用ssh登入,而不是sftp連線。

修改這行判斷式後就可以正常使用sftp了。
--
其實到最後還是不知道原因是什麼:

本來唯一可以使用的工作站,它的ssh版本是
OpenSSH_5.5p1, OpenSSL 1.0.0a 1 Jun 2010
其他兩台不能用的則是:
OpenSSH_5.1p1 Debian-5, OpenSSL 0.9.8o 01 Jun 2010
OpenSSH_3.9p1, OpenSSL 0.9.7a Feb 19 2003
不知道是不是1.0允許echo輸出文字的關係?這部分目前未明。

2013年7月8日 星期一

使用python執行EM模擬及寄信通知

runem這個小程式,主要是因為,通常我RF的電磁模擬要花上很多的時間,丟上工作站的話都要跑很久,如果是在windows下透過putty連結工作站,要是putty突然當掉,導致跑到一半的模擬中止掉就頭大了。

面對這個狀況有幾個解決方案,例如使用專面負責離線工作的程式,像是screen;但因為幾台工作站的作業系統太過老舊,上面甚至連screen都沒有;另一個解決方案是用atd,也就是linux內建的服務,在某個時間進行某個指令,這個解決方式很好,只是at 的語法比較麻煩,強迫每個使用者去記也沒什麼道理,身為網管要提供使用者方便,決定把at包成一個shell,使用者只要使用這個指令即可。

--

其實這個只要用shell script寫幾行即可,不過考量到一些特別的功能,還是用python來寫。 核心功能其實就一個,透過python 的subprocess把em 的指令透過atd送進去(ref 3):
cmd = "echo 'em -v {0}'".format(filename) 
cmd2 = "at now +0 minutes" 
p1 = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) 
p2 = subprocess.Popen(cmd2, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=p1.stdout)

監控程序:

啟動atd之後,必須要監控該執行程序,看看它是不是結束了,這裡我使用強者我同學AZ的python 解決方案: pnotify(ref 2)
當然,這個監控的程式也要用atd的方式來執行。

第一步是先找出atd呼叫出來的em -v的process,再來的function就是抄襲AZ的,簡單來說是先檢查/proc,看看該pid是否開啟,然後每隔一段時間就用kill 0的方式檢查該程序存在與否。
找出pid的部分,用的方法就笨一點,直接叫外部的ps,抓出有em的部分、濾出該使用者的資訊、排除grep自身,再用pid排個序,抓最大(最新)的pid即可,這個方法在pid用完一圈後會出錯,不過將就用一下,之後再看看有沒有更好的解,有的話麻煩強者們提示一下m(_ _)m:
pid_list = [] 
cmd = "sleep 1; ps -elf" 
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) 
stdout = p.stdout.read().decode("utf-8").split('\n') 
for line in stdout: 
    if ("em -v" in line) and (username in line) and ("grep" not in line): 
        pid_list.append(line.split()[3])

就可以抓出pid了。 再來再用atd開啟一個pnotify的監控工作即可。

email:

為了方便使用者,使用的是python + SMTP module,這部分的程式碼只能用明碼寫出帳號密碼,不過這在權限上設定為只有我能看即可;主要code如下:
 # open smtp session 
session = smtplib.SMTP('smtp.gmail.com', 587) 
session.ehlo 
session.starttls() 
session.ehlo 
session.login(account, password) 

# prepare the send message 
msg = MIMEText("Your EM simulation: {0} is over".format(filename)) 
msg['Subject'] = "the test title" 
msg['From'] = sender 
msg['To'] = receiver 


# send the message 
session.sendmail(sender, [receiver], msg.as_string()) 
session.quit()

透過google的smtp進行文件的轉送,其實這沒什麼,大部分都是抄的lol(ref 1)

成果:

現在工作站可以透過 runem file1.son 的方式執行一個超大em模擬,em模擬結束時候,可以透過電子郵件,通知進行模擬的使用者。
本程式透過python譔寫,相當快速,總開發時間約3-4天。
原始碼已上傳到github上:
https://github.com/lc85301/runem

附章:

趁著這次佈署runem的時候,順便佈署了另一個小script: clearcdslck
其實沒什麼,只是一個shell包含一行指令:
find . -name *.cdslck -exec rm -fv {} \;

方便使用者清除因不當結束產生的.cdslck檔。

參考資料:

1. about python mail using google SMTP
http://segfault.in/2010/12/sending-gmail-from-python/
2. about pnotify.py
http://blog.azhuang.me/2011/07/script-for-notifying-process.html#more
3. about python subprocess
http://docs.python.org/2/library/subprocess.html

致謝:

本文感謝AZ Huang同學的pnotify.py以及在SMTP使用上的指導,另外感謝同實驗室的曾奕恩大師幫忙測試本程式。