【AI白身境】只会用Python?g++,CMake和Makefile了解一下
文章首發于微信公眾號《有三AI》
【AI白身境】只會用Python?g++,CMake和Makefile了解一下
今天是新專欄《AI白身境》的第六篇,所謂白身,就是什么都不會,還沒有進入角色。
對于大部分小白來說,因為python用的太爽,以致于或許都沒有聽說過CMake。python是腳本語言,而當前大量的AI算法都部署在移動端嵌入式平臺,需要使用c/java語言,因此熟悉CMake和Makefile也是必備的基礎。
作者?|?湯興旺?言有三
編輯?|?湯興旺?言有三
?
01?g++必備基礎
在學習CMake和和Makefile之前我們先學下g++這個工具,大家或許會問為什么要學g++,不應該直接學CMake和Makefile嗎。實際上如果你不掌握g++根本就不會寫Makefile,因為它實際上就是對g++代碼的整理,有了Makefile,執行程序會更加快速方便。另外CMake就是為了簡化Makefile的編寫,它可以自動生成Makefile。
1.1?安裝g++
我們在安裝g++之前可以看一下自己是否已經安裝了g++,因為ubuntu安裝后就默認安裝了g++,下面命令可查看自己g++版本。
Tips:如果不想作死,就不要手賤去降級或者升級g++版本。
g++?--version
因為我已經安裝了g++,出現了上面安裝的版本號。如果你出現了上面信息,就不需要再安裝了,沒有的話,用下面的命令即可完成安裝。
sudo?apt-get?install?g++
安裝好后也可以通過g++?--version查看是否安裝成功
1.2?編譯流程
現在我們已經安裝好了g++,接下來通過寫一個簡單的程序來看看整個的編譯流程。
我們通過vim創建一個test.cpp文件,測試的代碼如下:
#include?<iostream>
using?namespace?std;
int?main()?
{????
??????cout?<<?"Hello,?world!"?<<endl;???
??????return?0;?
}
測試代碼完成后,我們來進行下編譯,打開終端,在終端輸入g++??文件名即可,在這個程序中就是下面命令:
g++??test.cpp
注意這里的文件名是包括路徑的,要是不知道文件路徑的話可以在敲完g++和空格之后直接把文件拖進去,系統會自動添加文件路徑。
在終端完成上面的命令后,你發現并沒有任何輸出,但這時候你去主文件夾下(默認主文件夾)看下會發現有個a.out文件
現在你再在終端輸入下面命令就能看到結果。
./a.out
接下來我來解釋下這個.out文件,實際上這是個經過相應的鏈接產生的可執行文件。還有個.o文件,它是個中間文件,一般是通過編譯的但還未鏈接。我們通過看看g++在執行編譯工作的時候的流程,你就會有更好的理解。如下:
1.預處理,生成.i的文件
2.將預處理后的文件轉換成匯編語言,生成.s文件
3.將匯編變為目標代碼(機器代碼),生成.o的文件
4.連接目標代碼,生成可執行程序
對于這個流程,我們結合上面的例子,再詳細介紹下,如下:
1.預處理階段
首先在終端輸入下面代碼:
g++?-E?test.cpp?>?test.i?
預處理后的文件在?linux下以.i為后綴名,這個過程是用來激活預處理,執行完命令后,你會發現主文件夾下多了一個test.i文件
這一步(預處理)主要做了宏的替換,和注釋的消除。
上圖是test.i文件的最后部分,可以看見宏的替換和注釋的消除。
2.將預處理后的文件轉換成匯編語言
在終端輸入下面代碼:
g++?-S?test.cpp
這一步主要就是生成test.s文件,.s文件表示匯編文件,用編輯器打開就都是匯編指令。下圖是test.s文件的一部分。
3.將匯編語言變為目標代碼(機器代碼)
在終端輸入下面代碼:
g++?-c?test.cpp?
這一步就是生成目標文件,用編輯器打開就都是二進制機器碼。
4.鏈接目標代碼,生成可執行程序
在終端輸入下面代碼:
g++?test.o?-o?test
在這一步中生成的可執行程序名為test,如果執行命令?g++?test.o??這樣默認生成a.out
最后我們再看下這個過程中產生的所有文件,如下:
這就是編譯的整個過程,你掌握了嗎,這個過程對于后面編寫Makefile非常重要,一定要深刻理解。
?
02?Makefile必備基礎
上面我們對g++和編譯過程進行了介紹,現在我們繼續學習如何編寫Makefile。
2.1?Makefile介紹????????????????????????
Makefile描述了整個工程的編譯、鏈接等規則,它定義了一系列規則來指定哪些文件需要編譯以及如何編譯、需要創建哪些庫文件以及如何創建這些庫文件、如何產生我們想要的可執行文件。
而且Makefile可以有效的減少大工程中需要編譯和鏈接的文件,只編譯和鏈接那些需要修改的文件,可以說使用Makefile,整個工程都可以完全自動化編譯。
2.2?Makefile基本格式
target?...?:?prerequisites?...
???command
???...
???...
target?-?目標文件,?可以是?Object?File,?也可以是可執行文件
prerequisites?-?生成target所需要的文件或者目標
command?-?make需要執行的命令(任意的shell命令),Makefile中的命令必須以?[tab]?開頭
2.3?Makefile語法
Makefile包含了五個重要的東西:顯示規則、隱晦規則、變量定義、文件指示和注釋。詳細解釋如下:
?1.?顯示規則:
通常在寫makefile時使用的都是顯式規則,這需要指明target和prerequisite文件。一條規則可以包含多個target,這意味著其中每個target的prerequisite都是相同的。當其中的一個target被修改后,整個規則中的其他target文件都會被重新編譯或執行。?
2.?隱晦規則:
make的自動推導功能所執行的規則
3.?變量的定義:
Makefile中定義的變量,一般是字符串
4.?文件指示:
Makefile中引用其他Makefile;指定Makefile中有效部分;定義一個多行命令?
5.?注釋:
Makefile只有行注釋?"#",?如果要使用或者輸出"#"字符,?需要進行轉義,?"\#
2.4?Makefile簡單實例
盡管上面介紹了許多Makefile的知識點,但我相信一定你很暈,接下來我通過一個實例來說明如何編寫Makefile。
2.4.1?準備程序文件
我們使用opencv對下面這只可愛的貓進行讀取顯示。
在這里我們用c++和opencv對圖片進行讀取和顯示,程序保存在DisplayImage.cpp這個文件里,代碼如下:
#include?<stdio.h>
#include?<opencv2/opencv.hpp>
using?namespace?cv;
int?main(int?argc,?char**?argv?)
{
????if?(?argc?!=?2?)
????{
???????printf("usage:?DisplayImage.out?<Image_Path>\n");
????????return?-1;
????}
???Mat?image;
????image?=?imread(?argv[1],?1?);
????if?(?!image.data?)
????{
????????printf("No?image?data?\n");
????????return?-1;
????}
????namedWindow("Display?Image",?WINDOW_AUTOSIZE?);
????imshow("Display?Image",?image);
????waitKey(0);
????return?0;
}
2.4.2?Makefile編寫
上面我們已經準備好了.cpp文件,現在我們來編寫Makefile進而進行編譯,程序如下:
現在我來解釋下應該如何編寫這個Makefile,對于編寫Makefile我建議從下往上寫。步驟如下:
1.編寫clean
這一步在Makefile中基本差不多,它的作用就是刪除所有的.o文件和可執行文件。為什么這樣做呢?我舉個例子說明下,如果你有100個.cpp文件,經過編譯后會得到一個可執行文件。在這個過程中我們會得到許多不必要的文件,例如100個.o文件,但這個文件又沒有用,如果用rm的話那就太麻煩了,所以我們用了clean,它可以很輕松完成這個任務。另外請注意Makefile文件在執行時不會執行clean這個命令,需要我們調用才會執行,即make?clean。clean代碼如下:
2.編寫目標文件1:依賴文件1
目標文件就是你想得到的文件,依賴文件就是你目前所擁有的東西。在本實例中我們現在擁有DisplayImage.cpp,所以DisplayImage.cpp是依賴文件,我們想得到DisplayImage.o,所以它是目標文件。代碼如下:
3.編寫目標文件2:依賴文件2
這一步的依賴文件2實際就是第二步的目標文件1,在第二步我們通過DisplayImage.cpp得到了DisplayImage.o,現在我們需要通過DisplayImage.o得到可執行文件DisplayImage。所以在這一步目標文件是DisplayImage,依賴文件是DisplayImage.o,代碼如下:
4.應用opencv庫和頭文件
這一步就需要根據自己計算機來配置了,對于我們初學者來說挺麻煩的,可以自己嘗試下。有問題可以聯系我們。
編寫完makefile后,我們在終端make下就行了。下面編譯后的文件:
最后在終端輸入下面代碼即可顯示圖片。
./DisplayImage?01.jpg
總體來說編寫Makefile可以按照這個套路寫,多寫幾次就會了。
?
03?CMake必備基礎
說完Makefile,我們再說下CMake。CMake是一個跨平臺的編譯(Build)工具,可以用簡單的語句來描述所有平臺的編譯過程,其是在make基礎上發展而來的,早期的make需要程序員寫Makefile文件,進行編譯,而現在CMake能夠通過對cmakelists.txt的編輯,輕松實現對復雜工程的組織。下面我帶大家學習下CMake的基礎知識。
3.1?安裝CMake
首先我們看看如何在自己的linux系統(我的系統Ubuntu18.04)下安裝CMake。方法如下:
sudo?apt-get?install?cmake
輸入上面命令后實際上就安裝成功了,可以通過下面命令來檢查:
cmake?--version
如果你的界面如下圖所示即說明安裝成功。
3.2?CMake編譯流程
成功安裝好CMake后我們再來說說如何在linux平臺下使用CMake生成Makefile并編譯的流程,如下:
1.編寫CMake配置文件CMakeLists.txt,我們可以認為CMakeLists.txt就是CMake所處理的"代碼"。
2.執行命令?cmake?path生成Makefile,其中path是CMakeLists.txt所在的目錄。
3.使用make命令進行編譯。
3.3?使用CMake編譯程序
我們通過一個關于opencv讀取圖片的程序,讓大家更好的理解整個CMake的編譯過程。
3.3.1?準備程序文件
這里程序準備可以按照第二部分makefile那里準備。最后文件目錄結構如下:
├──?build
├──?CMakeLists.txt
├──?DisplayImage.cpp
opencv讀取圖片的程序寫完后,我們需要編寫CMake處理的代碼了,即CMakeLists.txt。
3.3.2?編寫CMakeLists.txt
現在我們編寫CMakeLists.txt文件,該文件實際上放在哪里都可以,只要編寫的路徑能夠正確指向就好了,CMakeLists.txt文件內容如下所示:
cmake_minimum_required(VERSION?2.8)
project(?DisplayImage?)
find_package(?OpenCV?REQUIRED?)
add_executable(?DisplayImage?DisplayImage.cpp?)
target_link_libraries(?DisplayImage?${OpenCV_LIBS}?)
看到這些代碼是不是很悶逼,為了讓大家明白CMakeLists.txt文件內容,接下來我說一下Cmake的一些常用命令,你就能很好的理解上面的代碼了。
1)cmake_minimum_required命令
命令語法:cmake_minimum_required(VERSION?major[.minor[.patch[.tweak]]][FATAL_ERROR])
命令簡述:用于指定需要的CMake?的最低版本
使用范例:cmake_minimum_required(VERSION?2.8)
2)project?命令
命令語法:project(<projectname>?[languageName1?languageName2?…?]?)
命令簡述:用于指定項目的名稱,一般和項目的文件夾名稱對應
使用范例:project(DisplayImage)
3)aux_source_directory命令
命令語法:aux_source_directory(<dir>?<variable>)
命令簡述:用于將?dir?目錄下的所有源文件的名字保存在變量?variable?中
使用范例:aux_source_directory(src?DIR_SRCS)
4)add_executable?命令
命令語法:add_executable(<name>?[WIN32]?[MACOSX_BUNDLE][EXCLUDE_FROM_ALL]?source1?source2?…sourceN)
命令簡述:用于指定從一組源文件?source1?source2?…?sourceN?編譯出一個可執行文件且命名為name
使用范例:add_executable(?DisplayImage?DisplayImage.cpp?)
5)target_link_libraries命令
命令語法:target_link_libraries(<target>?[item1?[item2?[…]]][[debug|optimized|general]?]?…)
命令簡述:用于指定?target?需要的鏈接?item1?item2?…。這里?target?必須已經被創建,鏈接的?item?可以是已經存在的?target(依賴關系會自動添加)
使用范例:target_link_libraries(?DisplayImage?${OpenCV_LIBS}?)
6)add_subdirectory?命令
命令語法:add_subdirectory(source_dir?[binary_dir]?[EXCLUDE_FROM_ALL])
命令簡述:用于添加一個需要進行構建的子目錄
使用范例:add_subdirectory(Lib)
7)include_directories?命令
命令語法:include_directories([AFTER|BEFORE]?[SYSTEM]?dir1?dir2?…)
命令簡述:用于設定目錄,這些設定的目錄將被編譯器用來查找?include?文件
使用范例:include_directories(${PROJECT_SOURCE_DIR}/lib)
像這樣的命令還有很多,如find_package()尋找使用第三方庫等,這些都需要我們平時多加積累。給大家一個查詢命令的方法,大家可以多去看cmake官網的help,鏈接如下:
https://cmake.org/cmake/help/v2.8.8/cmake.html#section_Commands
3.3?編譯和運行程序
現在CMakeLists.txt文件已經編寫好了,意味著我們的工作即將進入尾聲。現在看看我們的文件結構目錄,如下圖:
接下來我們就需要進行編譯了。編譯的過程相對于CMakeLists.txt文件的編寫是很簡單的,只有兩步,如下
cmake
make
其中cmake命令將CMakeLists.txt文件轉化為make所需要的makefile文件,最后用make命令編譯源碼生成可執行程序或共享庫。對于我們這個實例,編譯如下:
首先我們在命令行輸入cmake?.(注意cmake和.之間有空格),表明Cmakelist.txt文件在當前目錄下。
接下來在命令行輸入make
這樣我們就編譯成功了,我們看下編譯后的文件目錄
解釋下這個build文件夾,由于cmake后會生成很多編譯的中間文件以及makefile文件,所以一般建議新建一個新的目錄,專門用來編譯,這就是這里的build,打開build后,里面的文件如下:
到這里,我們不禁要問怎么沒有圖片顯示呢,別急,在build目錄下的命令行輸入下面命令即可顯示圖片,這就是生產的DisplayImage可執行文件。
./DisplayImage?../01.jpg
到這里,關于CMake的一些基本操作就介紹的差不多了,其實對于CMake的學習我認為必須在實例中多加應用,才能更好的掌握,因為它的復雜命令太多了。
?
總結
CMake和Makefile的基礎我們就介紹完了,對于這兩個工具其實不是一時就能學會的,需要大量的實踐積累才能游刃有余。
下期預告:下一期我們會講AI領域必須掌握的數據爬蟲基礎,如果你有建議,歡迎留言,我們會及時采納的。
?
轉載文章請后臺聯系
侵權必究
AI白身境系列完整閱讀:
第一期:【AI白身境】深度學習從棄用windows開始
第二期:【AI白身境】Linux干活三板斧,shell、vim和git
第三期:【AI白身境】學AI必備的python基礎
第四期:【AI白身境】深度學習必備圖像基礎
第五期:【AI白身境】搞計算機視覺必備的OpenCV入門基礎
第六期:【AI白身境】只會用Python?g++,CMake和Makefile了解一下
第七期:【AI白身境】學深度學習你不得不知的爬蟲基礎
第八期:?【AI白身境】深度學習中的數據可視化
第九期:【AI白身境】入行AI需要什么數學基礎:左手矩陣論,右手微積分
第十期:【AI白身境】一文覽盡計算機視覺研究方向
第十一期:【AI白身境】AI+,都加在哪些應用領域了
第十二期:【AI白身境】究竟誰是paper之王,全球前10的計算機科學家
AI初識境系列完整閱讀
第一期:【AI初識境】從3次人工智能潮起潮落說起
第二期:【AI初識境】從頭理解神經網絡-內行與外行的分水嶺
第三期:【AI初識境】近20年深度學習在圖像領域的重要進展節點
第四期:【AI初識境】激活函數:從人工設計到自動搜索
第五期:【AI初識境】什么是深度學習成功的開始?參數初始化
第六期:【AI初識境】深度學習模型中的Normalization,你懂了多少?
第七期:【AI初識境】為了圍剿SGD大家這些年想過的那十幾招
第八期:【AI初識境】被Hinton,DeepMind和斯坦福嫌棄的池化,到底是什么?
第九期:【AI初識境】如何增加深度學習模型的泛化能力
第十期:【AI初識境】深度學習模型評估,從圖像分類到生成模型
第十一期:【AI初識境】深度學習中常用的損失函數有哪些?
第十二期:【AI初識境】給深度學習新手開始項目時的10條建議
感謝各位看官的耐心閱讀,不足之處希望多多指教。后續內容將會不定期奉上,歡迎大家關注有三公眾號 有三AI!
?
總結
以上是生活随笔為你收集整理的【AI白身境】只会用Python?g++,CMake和Makefile了解一下的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【AI白身境】搞计算机视觉必备的Open
- 下一篇: 【cntk速成】cntk图像分类从模型自