VOOZH about

URL: https://read01.com/R5x2Na.html

⇱ 一點開發環境設計經驗 - 壹讀


Sunday, Apr 12, 2026

一點開發環境設計經驗

2015/12/02 來源:cnblogs

開發環境設計是個簡單,卻又非常不簡單的事,當然結果也就是天壤之別。

比如我曾經混過的一個外包項目,竟然需要每個開發人員除了要從SVN下載應用源碼外,還要一份Nuclear作業系統副本。編譯的時候,自然也就要先編譯作業系統了。搞個bug,要忍受跟SVN磨嘰一兩個鐘頭,花半個鐘將代碼加入SourceInsight,修改幾行代碼後,再跟編譯器折騰個把鍾,然後再SVN……就這樣,日復一日,年復一年。當然,現實沒那麼誇張,但我給那些開發人員做個了統計,證實每天花不少於2小時在編譯、版本管理等。當然,必要的編譯、版本管理等工作也是需要時間的,但絕不應該那麼多。試想一下,源碼縮減到只有幾兆,數十兆,或是百來兆,那下載一次代碼的時間則能在數分鐘內完成;將作業系統,平台做成庫文件提供,應用開發人員只編譯應用部分並連結庫文件,則幾分鐘就能做完一次版本編譯。如此一來,節約下來的時間相對客觀。更重要的是,人的心情會變好~~

另一個直接受開發環境影響的,就是代碼層次結構了。想一想,看到一個C, C++的源文件的開始是十幾,數十行#include,外加幾個編譯選項宏的時候會不會瘋掉。然後呢,Makefile里又是一堆-I路徑。我最怕這個了,找個編譯錯誤都能有經歷千山萬水的成就感。很多時候,得將些頭文件,和頭文件的內容進行挪移,甚至另起爐灶(這招太損,但既然都這麼搞,也只能入鄉隨俗)。

編譯前:

1. vob/xxx_prj/

1.1............build/

1.2............cmd/

1.3............tools/

1.4............export/

1.5............cshell/

1.5.1.................export/

1.5.2.................inc/

1.6............userapp/

1.6.1.................export/

1.7.2.................inc/

編譯後:

1. vob/xxx_prj/

1.0............bin/

1.0.1..............linux.i32

1.0.2..............linux.i64

1.1............build/

1.2............cmd/

1.3............tools/

1.4............export/

1.5............cshell/

1.5.1.................export/

1.5.2.................inc/

1.5.3.................bin/

1.5.3.1linux.i32/

1.5.3.2linux.i64/

1.6............userapp/

1.6.1.................export/

1.6.2.................inc/

1.6.3.................bin/

1.6.3.1linux.i32/

1.6.3.2linux.i64/

相對編譯前,編譯後的各級源碼目錄下多了個bin目錄,裡面包含多個子目標。通常來說,一個項目下會生成針對不同功能板卡的多個可執行文件,因此項目根目錄應當包含多個userapp目錄,而不同硬體、版本的板塊,則在bin目錄下使用不同的目標類型存放編譯結果。

這裡特別的東西,就是export目錄,承擔著開發環境設計的畫龍點睛之重擔。幾乎肯定的,export極少被開發環境設計者認識。這是個很悲哀的事,一旦在項目開始時擦肩而過,幾乎只能永遠錯過了。而隨之帶來的,就是項目開發成本和維護成本攀升,軟體越做越複雜。我講這個,時常被人反駁,代碼多了,自然越來越複雜。

扯淡!你見過土豪因為錢多了而花錢煩惱麼?我們做程序的沒錢,代碼就是財富,項目開展一段時間後,代碼多了只應該使一切更容易,因為此時隱藏問題,目標更清晰,還有了更多可用的,可靠的組件,工具。

子目錄export什麼來頭?它裡面存放的,是可以供模塊外引用的頭文件,如宏,變量和函數的聲明。與export對應的,是模塊內頭文件inc目錄,存放的都是些模塊內使用的頭文件。如此一來,C語言的程序,從某種意義上就有了面向對象的public和private接口特徵。外部模塊是不能越過編譯限制來訪問inc的頭文件的,這一點可以通過makefile來控制。版本管理者則可以在無需理解源碼的前提下,通過編譯來發現錯誤的引用,而他所要做的,就是確保makefile不被未授權的修改。我以前做的比較絕,版本編譯前,強行重新生成各模塊的makefile(從標準模塊庫複製)。這樣一來,任何想突破規則的改動,都會被編譯器抱怨。

開發環境設計,另一個要點是,避免大量的#include<xxx.h>。這個不是那麼絕對,但如果項目是新的,就應該避免應用模塊用;如果只是個新模塊,則應該採取設置邊界edger.c來隔絕。要做到避免系統頭文件,項目根目錄export應該提供至少兩個組件:prj_type.h和sal_os.h。在我做到項目里,它們會被命名成zType_Def.h和salOS.h。zType_Def.h包含了一些基礎類型的定義,如byte_t, word_t, dword_t, lword_t,平台特定的zMsg_t, zHandle_t,甚至一些方便變成的宏定義MAX,_STR等等。這裡只有一個原則,就是一切都必須跟作業系統無關。salOS.h則是一些系統頭文件提供內容的封裝,比如memset被重新定義成zMemset,time被重新定義成zTime,等等。當然,salOS也是跟作業系統無關的,salOS里可以出現#include<xxx>引用系統頭文件,但限定為通用的系統頭文件。如ws_sock.h這類特定系統的頭文件,則不可以暴露在salOS.h裡面,必須在salNet.c等模塊里進行封裝後,在salOS.h中提供作業系統無關的接口函數。

zType_Def是必須強制被所欲應用程式引用的,salOS則根據應用的情況決定。但不管咋樣,這兩個文件都是軟硬體無關的。換句話說,當我們開發一個給嵌入式目標板使用的程序時,有機會在Linux一類的系統上進行大部分功能的調試工作。當然,大多時候光有type和salOS是不夠的,還需要個salHW。salHW是具體目標系統相關的,實現對真實硬體接口的一個橫向封裝,而在模擬環境下提供一套基本的硬體行為模擬。salOS和salHW所對應的實現,需要存放在不同的子目錄。這樣,通過makefile可以很容易的控制具體需要編譯、連結哪個。

我相當反對應用程式開發者直接使用printf,malloc等一類系統函數,在一個稍微大一點點的項目,它們總是會帶來災難。比如,我剛開始做移動核心網時,出現了無法關閉的一兩個列印。這是電信運營商眼裡是絕不容許的,幸好,很快等到一個計劃中的版本升級,否則那一年的無故障運行時間,就不可能達成5個9了。有了type和salOS等頭文件,在應付列印,內存泄漏等問題,就容易多了(這點以後聊)。

說了半天,都是防範濫用頭文件問題,但沒說過如何防範頭文件爛設計問題。確實,很多開發人員偷懶,把所有東西都扔到export目錄,inc目錄總是空空的。說實話,哥拿這類人真沒什麼辦法,也只有空想者拿刀砍人!

posted on2015-12-02 15:01hhao020閱讀(...) 評論(...)編輯收藏

您可能感興趣
免責聲明:本文內容來源于cnblogs,文章觀點不代表壹讀立場,如若侵犯到您的權益,或涉不實謠言,敬請向我們提出檢舉
最新文章 / 服務條款 / 私隱保護 / DMCA / 聯絡我們

壹讀/READ01.COM