九月時工作上接到一項任務,內容是評估某硬體方案的可能性。該硬體設備廠商有提供 Windows 與 Linux 兩種方案讓客戶選擇,為了趕進度,所以直接以熟悉的 Windows 方案使用 C# 進行試作,可惜評估結果不盡人意(硬體問題)。然而在此評估過程中,也讓我意識到 Linux 可能也是商用硬體設備的選項之一,所以在中秋節連假期間,除了吃飯睡覺拉屎看電視打電動逛街人擠人之外,把剩下的時間全都花在學習建置「Linux 環境開發 C/C++」這件事情上了。四天連假結束,算是有點收獲,開篇文章把這些學習心得記錄下來,免得以後很快又忘記。
這篇文章以「在 Linux 環境下開發 MQTT C/C++ Client 應用程式」為目標情境,打造 Linux 環境下相對友善的 C/C++ 開發環境,使用 Linux 版 IDE 工具進行 C/C++ 程式開發。
為何要以「開發 MQTT C/C++ Client」作為目標情境?原因是牽涉到 IDE 開發工具中引入 Library (函式庫套件)編譯的設定指令,大部分應用軟體一定是這麼做,所以拿 MQTT C/C++ Library 作為範例情境。如果只是在 Linux 環境下用 IDE 寫個 print Hello World ,就不用特意寫這篇文章來記錄了。
一、準備工作
一台運作 Ubuntu 18.04 並可連結 Internet 的電腦,虛擬機器也行。(Linux Ubuntu 18.04 下載網址)
二、基本技能
- 使用 IDE 開發程式的基本經驗
- Linux 終端機環境基本指令操作
三、設置 Linux 基本開發環境
本文以 MQTT C/C++ Client 為例,所以先把 MQTT 的可運作環境架起來,意思是在 Ubuntu 電腦上安裝 MQTT Broker 就行了。在安裝 MQTT Broker 之前,記得要用終端機跑一次套件更新:
$ sudo apt update && sudo apt upgrade -y
3.1 安裝 Mosquitto MQTT Broker
Linux(Ubuntu)安裝 MQTT Broker 超簡單!終端機一行指令搞定。
$ sudo apt install mosquitto mosquitto-clients -y
等安裝程序跑完就可以了。可以用 service mosquitto status 查看 MQTT Broker 的狀態,亮綠燈寫著 active (running) 就代表運作中。
如果不死心還想測試 MQTT 是否能正常運作,可以開兩個終端機視窗,各自輸入指令就行了。
以上圖來說,下方的視窗發出「Hello world 測試」的內容,上面的視窗有接收到。
3.2 安裝 Eclipse Paho MQTT C/C++ Client Library
嚴格來說得分成兩個部分:C Library 與 C++ Library,不過 Eclipse Paho 的 MQTT C++ Client Library 又依附在 MQTT C Client Library 上,換句話說不僅兩個都要安裝,而且要先安裝 C Library 再安裝 C++ Library。聽起有點複雜,其實官方也幫我們把安裝 C Library -> 安裝 C++ Library 的自動腳本都做好了,跟著以下指令操作即可:
$ sudo apt install git build-essential gcc make cmake cmake-gui cmake-curses-gui libssl-dev doxygen graphviz libcppunit-dev -y
$ cd ~
$ git clone https://github.com/eclipse/paho.mqtt.cpp
$ cd paho.mqtt.cpp
$ ./install_paho_mqtt_c.sh
$ cmake -Bbuild -H. -DPAHO_BUILD_DOCUMENTATION=TRUE -DPAHO_BUILD_SAMPLES=FALSE
$ sudo cmake --build build/ --target install
$ sudo ldconfig
指令看起來有點多,不過整個做完也差不多一兩分鐘而已。跑完之後,/usr/local/lib 與 /usr/local/include 兩個目錄下會新增一些 MQTT 用到的 Library 二進位檔與 .h 標頭檔如下:
做到這裡,C/C++ MQTT Client Library 套件就已經安裝設置完成,找個範例程式試著編譯執行看看。以 ~/paho.mqtt.cpp/src/samples 底下的 topic_publish.cpp 範例程式為例:
$ cd ~/paho.mqtt.cpp/src/samples
$ g++ -g -o topic_publish topic_publish.cpp -lpaho-mqttpp3 -lpaho-mqtt3cs -lpaho-mqtt3as -lstdc++
$ ./topic_publish
若編譯和執行都沒出現錯誤訊息,表示已經可以在這個環境下用 C/C++ 撰寫與編譯 MQTT 的應用程式了。在 -o xxxx 後面的一大串參數,就是編譯時需引用的程式碼或 Library 函式庫。
確認 Library 安裝設置很重要,若沒弄好,後面 IDE 的編譯設置也會跟著出問題。所以要確認上面的動作都沒問題之後,後面導入 IDE 的動作才能繼續。
四、C/C++ 的 IDE 工具設定
接下來簡單介紹兩款支援 Linux 環境的 C/C++ IDE 開發工具:Eclipse 公司的 Eclipse for C/C++,以及微軟的 Visual Studio Code(簡稱 VSCode)。
兩款工具都需要經過若干設定才能用於開發 C/C++,Eclipse 設定相對簡單但使用上不直覺(不好用),而 VSCode 則是反過來,設定複雜但容易使用,且提示功能強大。要使用哪一種端看個人習慣與喜好。
接下來以上述的 topic_publish.cpp 為例,說明如何把現成的程式導入 IDE 進行開發撰寫與除錯。
首先必須先把 topic_publish.cpp 程式做基本的「專案化」,也就是先建立新目錄,將程式複製到新目錄之後,並在該目錄將編譯指令做成 Makefile 文字檔。操作方式:
(1) 將 topic_publish.cpp 複製到 ~/[新目錄]/topic_publish.cpp ,這裏新目錄名稱用 topic_publish。
(2) 在此目錄下手動建立 Makefile 設定檔(nano Makefile),內容如下
all:
g++ -g -o topic_publish topic_publish.cpp -lpaho-mqttpp3 -lpaho-mqtt3cs -lpaho-mqtt3as -lstdc++
clean:
rm topic_publish
要強調的是,指令的前面要用 Tab 鍵而非空白鍵,也就是 g++ 與 rm 的前面是 Tab 而非空白,這點非常重要!最後存檔離開。
接著在目錄下執行 make 指令,看看編譯時會不會依照 Makefile 指令進行編譯。
若沒什麼錯誤訊息,表示 topic_publish.cpp 程式的「專案化」完成。接著就能把這個「專案」導入 IDE 工具了。
4.1 Eclipse
4.1.1 下載 Eclipse
Eclipse 下載網址:https://www.eclipse.org/downloads/packages/
選擇「Eclipse IDE for C/C++ Developers」的 Linux 64-bit 版下載即可。
下載檔案是 .tar.gz 壓縮檔,直接點擊後會開啟壓縮檔管理員,把壓縮檔內的 eclipse 目錄,直接拖曳就行了(建議安裝在 [家目錄] ,後續比較方便)。
進入 eclipse 之後,直接點擊 eclipse 執行檔就可運行 Eclipse。
4.1.2 使用 Eclipse 開發 C/C++
啟動運行 Eclipse,第一次執行會問 workspace 的目錄,不做任何更動,點擊 Launch
點擊「Import a project with a working Makefile」
依下圖步驟 1. ->2. ->3. :
選擇 ~/topic_publish 目錄,點擊 Linux GCC,按 Fihish 。
把「Welcome」頁籤關掉,終於進入 C/C++ 開發介面模式。
可以看得出開發介面的功能相當完整但有點複雜,上就是上圖標示出來的那些比較重要,細節請自行 Google。然後即使匯入專案,仍少了 Launch Configuration 設定。(上圖紅框)。
然後重點來了...在專案名稱上按右鍵 --> Build Project。這麼做的目的是先讓 Eclipse IDE 跑一遍 Makefile 的設定並自動偵測,否則後面無法使用 Launch Configuration 設定精靈。
接著點擊新增 Launch Configuration 開啟設定精靈。
按 Next ,
可設定 Launch Configuration 名稱,若不設定直接按 Finish 即可。
這樣就大致設定完成了。
4.1.3 Eclipse 的一般 IDE 功能:
支援一般 IDE 該有的功能,例如自動完成(AutoComplete),顯示定義,以及 Debug Break Point 等。
上述可以發現 Eclipse 提供了精靈工具,在執行設定步驟時多半是根據指示下一步就完成了,但精靈設定還是不夠親民,有時不小心搞錯一個動作,就會搞不懂為何沒有下一步的選項。
4.2 微軟 Visual Studio Code(VSCode)
我在先前寫過 VSCode 撰寫 python 與 PHP 的文章,設定上雖然不複雜,但還是有些很神奇的騷操作。沒想到 VSCode 撰寫 C/C++ 的設定更是奇葩,騷操作更多。
不過搞定這些騷操作之後,用起來的感覺真的很不錯,還有一大堆外掛可滿足個人特定需求。所以比起 Eclipse,我個人是推薦使用 VSCode 來開發 C/C++。
在此先強調一個觀念:用 VSCode 撰寫 C/C++ 需先在專案根目錄底下的 .vscode 子目錄內建立三個設定檔:c_cpp_properties.json,tasks.json,launch.json。不過找了一大堆網路教學,全都沒交代這三個檔案是怎麼生出來的,格式跟項目為何要長成那樣。雖然最笨的方式雖然可以手動一個字一個字敲打產生,但完全不建議這麼做。
事實上可以透過一堆騷操作生成三個設定檔,產生之後只需針對專案的特性,修改局部微調即可,偏偏網路教學很多都是抄來抄去,全都沒有介紹如何自動生成(不知是否因為下錯關鍵字,總之我找了很久沒找到),所以光是 C/C++ 的設定檔騷操作我就式了將近一天,總算搞出設定檔的生成流程。
三個設定檔的生成還有順序,順序錯了生成的內容也會跟著錯,大家都說「Visual Studio」 是地表最神的 IDE 工具,但為何多一個 Code 字,就得搞得如此折騰人生呢?微軟啊微軟,我真的是搞不懂你....
好了,牢騷發完,進入正題。
4.2.1 下載並安裝:下載網址,選 .deb 版即可。
下載後直接點擊 .deb 檔進行安裝,依照畫面指示進行安裝即可。安裝完成之後,應用程式列表就會出現熟悉的 Visudl Studio Code 圖示。在終端機內輸入「code」也能啟動。
4.2.2 使用 Visual Studio Code 進行 C/C++ 開發
(1)開啟終端機,進入專案目錄 ~/topic_publish,在該目錄底下執行指令「code .」(注意 code 後面有個「點」號)
$ cd ~/topic_publish
$ code .
接著就會開啟 VSCode 並自動將 topic_publish 專案導入。以下是介面概述:
主動提示區的功能很好用,會自動預測你現在可能想做什麼而作出提示,例如有時會建議你可能遇到什麼問題,安裝什麼插件或做什麼操作可以解決。當然了,如果預測不是想要的,可以點擊 X 不理它。這裡就不提主動提示區的功能了。
第一件事,就是安裝需要的插件,點擊插件市集按鈕,安裝以下五個插件:
Bracket Pair Colorizer:不同括號層級顯示不同括號顏色(已內建於 Visual Studio Code)- C/C++ for Visual Studio Code:微軟自帶的C/C++外掛。
- C/C++ Clang Command Adapter:提供靜態檢測(Lint)
- C++ Intellisense:一組功能的名稱,這些功能可讓撰寫程式碼變得更方便。
- Include Autocomplete:提供標頭檔案名字的補全。
其他插件參考
- C/C++ Snippets:自動插入程式碼片段。
- C++ Helper:提供撰寫 C++ 程式時一些好用的快速功能。
- Doxygen Documentation Generator:產生程式碼說明註解的好東西。
- theme-chromodynamics:熟悉的佈景主題。
- Chinese (Traditional) Language Pack for Visual Studio Code:介面中文化。
4.2.3 依序產生三個設定檔
三個設定檔依序為
- c_cpp_properties.json
- tasks.json
- launch.json
三個設定檔都在專案目錄的 .vscode 子目錄下。上面提到三個設定檔也必須依照順序生成,接下來就是進入連續騷操作的步驟,所有的操作都有個重點:把編輯區視窗停留在 .cpp 主檔案上,再進行相關操作。
(1) 生成第一個設定檔:c_cpp_properties.json。
依下圖 1. -> 2. -> 3. -> 4.
接著出現命令框,選擇「C/C++:Edit Configurations (UI)」(或是「C/C++:Edit Configurations (JSON) 也可以」。
出現選項式的介面,原則上都不需要更動任何設定。
將「C/C++ Configuration」頁籤關閉。然後就可以看到在 .vscode 目錄下自動產生第一個設定檔「c_cpp_properties.json」。可以透過下圖的 1. -> 2. 查看,原則上不需任何更動。
然後必須再回到點擊 .cpp 上,否則後面的生成動作會出錯。
(2) 接著繼續生成第二個設定檔:tasks.json。
在回到 .cpp 的前提下,依下圖點擊 1. Terminal -> 2. Configure Default Task...
會開啟選擇視窗。意思是選擇不同的編譯器,基本上選擇哪一個都可以,我選擇 gcc 這一項。第二個設定檔 tasks.json 也會自動生成。
不過 tasks.json 內的 args 參數必須手動修正,原因是 topic_publish.cpp 必須引用 MQTT C++ Client 的參數才能正常編譯。參考 Makefile 內容,加入一些編譯參數如下:
第二個 tasks.json 也完成了。務必再把視窗切回到 topic_publish.cpp。
(3) 接下來,生成第三個設定檔:launch.json。
依下圖點擊 1.Run -> 2. Open Confighration
跳出選擇項目,選擇「C++ (GDB/LLDB」
又一層選擇視窗,原則上選哪一個都一樣。由於前面已經選擇了 gcc,這裏也一樣選擇 gcc 項目
第三個設定 launch.json 也會自動生成,並且 VSCode 會順便自動跑一下相關設定,也會自動切換到除錯模式。正常的話切下方換到 TERMINAL 視窗(如下圖)可以看到程式編譯完成也跑過一遍。
這樣就大致完成專案的設定了。依上述的操操作,只需要修改 tasks.json 的 args 項目,加入必要的 Library 而已,其他都不用特別更動。
4.2.4 Visual Studio Code 開發 C/C++ 的一般 IDE 功能:
支援一般 IDE 該有的功能,例如自動完成(AutoComplete),顯示定義,以及 Debug Break Point 、顯示變數值等。
五、後記
以上只是短短四天的個人學習心得,也只算是 IDE for C/C++ 設定的最.最.最....最初步入門而已,IDE for C/C++ 真正的用法應該不只有這樣,像是 CMake 這類進階的用法。哪天有研究出更好用的方式,會再回頭過來補完這篇文章。
(2020.10.25 補充)經過一段時間的摸索,透過使用 VSCode 找到更簡單的設定方式。使用一個叫「Fenix」的延伸插件就行了。透過這個插件,可以很輕鬆的產生 C++ 專案設定。
首先先用 MSCode 開啟一個新的空白的目錄,我們將在這個目錄產生新的 C++ 專案。在 Fenix 安裝啟用之後,左邊會出現新的圖示。依下圖的順序指示點擊:1. 圖示 -> 2. Easy C++ Projects -> 3. +號 -> 4. Open Fenix
接著會出現 Fenix 的主畫面,再依序點擊 5.Language C++ -> 6. [G++/GDB] -> 7. Create
切回專案的檔案總管(下圖左邊紅框圖示),就可以看到產生一個最基本的 C++ 專案了。它已經幫你把 Makefile 和 VSCode 最重要的兩個設定:tasks.json 與 launch.json 都弄好了。
最近研究在研究 Makefile 的撰寫,說真的 Makefile 也是一門深奧的學問,網路教學也不少。這個自動產生的 Makefile 內容長這樣:
不過後來我在練習撰寫時,發現這個 Makefile 是有問題的。在預設產生 Makefile 內容的第 20 行,必須要改成這樣:
$(CXX) -I$(INCLUDE) -L$(LIB) $^ -o $@ $(LIBRARIES) $(CXX_FLAGS)
也就是要將 $(CXX_FLAGS) 移到最右邊,後續在使用時才不會有問題。
六、初步成果
經過多日的練習,我做了一個 C++ 專案放在 Github 上(BeMqttSample):
專案的目的是使用 paho.mqtt.cpp 另外再撰寫了自訂 class 類別 BeMqttClient,讓 MQTT Client 更直覺、簡單,容易使用,最短只需三行宣告就能驅動 MQTT Client 運行。這個專案就是用這篇文章提到的內容(paho.mqtt.c/cpp Client library,Makefile,Microsoft Visual Studio Code...),一步一步慢慢兜出來的。
修改了預設的 Makefile 的內容,加入 include 目錄的 cpp 編譯(因為 BeMqttClient 的原始碼放在這裡),並可支援 macOS 與 Linux 的環境(因為 macOS 沒有 -luuid 否則編譯會出錯。-luuid 是 Linux 環境下的 uuid 套件,亦需用 apt 安裝 uuid-dev 才能使用。)
若對這個自訂 class 類別內容有興趣的話,請讀者們自行上 github.com/benjenq/BeMqttSample 參考囉!
留言列表