對於windows程序員來說,在linux上開發C++程序會非常困難,一來沒用過makefile,其語法非常生澀難懂,二來vs之外的IDE,其易用性與vs相差甚遠,宇宙第一IDE不是蓋的。致使C++不同於其他編程語言,硬生生催生出Windows程序員和Linux程序員兩個群體,直到有了CMake。
常用開源庫的同學想必對CMake非常熟悉,它可以在Linux上可以自動生成makefile,在Windows下可以生成vs解決方案sln,對於大規模跨平台項目絕對是首選,只不過Linux程序員用的多。相對於makefile,CMake語法要簡單的多,一周包教包會,走向人生巔峰。現在程序員的福音來了,visual studio在2017以后已經支持了CMake語法,使用vs2017可以在windows下寫程序,在linux下編譯,真的很方便。雖然現在的版本還不太成熟,偶爾會出現一些迷之錯誤,但相信以后這都不是事。真希望有一天,大家都用上vs2017。
廢話不多說,我以實戰入手,從我的代碼搬遷開始說起,我原先的代碼是用vs2013開發的,第三方庫頭文件和庫文件的管理都是通過vs屬性頁管理的,程序間互相依賴是通過引用完成的。如圖所示:
想必這些對windows程序員都非常熟悉,vs就是通過這樣管理項目的。我下面逐步介紹一下我這個工程是如何搬遷到linux上運行的。
一、建立工程目錄
如果你在裝vs2017的時候勾選了cmake,點擊新建->項目時會出現cmake選項,點擊確定,建立一個工程文件夾。
cmake會自動為我們創建如下文件,CMakeLists.txt就是管理當前文件夾下文件的配置文件,由於我一個文件夾里放一個工程,因此其地位相當於vs的vsproject,好像其不能改名,只能這么命名,不管它。子文件夾cmake_test是自動生成的,我並不打算將我的根目錄叫這個名字,刪除之:
新建我的源代碼文件根目錄src,並向其添加CMakeLists.txt
打開根目錄的CMakeList.txt,其中可以寫入對整個工程的配置:
cmake_minimum_required用來設置cmake的最低版本,如果所使用低於最低版本會報錯。project用來設置整個工程的名字,add_subdirectory用來對子目錄進行管理,這里我們只有一個子目錄src,將其加進來。cmake語法不區分大小寫,這里為了與其他語法相區別,統一都用大寫。set命令通常用來設置變量,CMake自身有許多預定義變量,可以通過set給它們賦值,如CMAKE_MOULE_PATH里面就指向了.cmake文件的搜索目錄,這通常會被用在第三方庫的搜索上面,它同時也有默認值,如CMAKE_SOURCE_DIR就是指向了根目錄,這里就是將根目錄下cmake文件夾作為第三方庫搜索文件所在目錄。
二、加入源代碼
在子文件夾src中遷移源代碼,按工程新建文件夾
src文件夾下的CMakeList.txt用來對源代碼文件夾進行管理,其cmake代碼如下:
很簡單,把各自子項目的源代碼文件夾加進來就可以了。將vs各工程內的.h、.cpp都復制到cmake子項目文件夾下,並在其內新建CMakeLists.txt
其文件夾下的CMakeLists.txt是對本工程下源代碼文件的管理
PROJECT就是該工程的名字,FILE是文件操作命令,其作用是將所有cpp文件存入base_src變量內,GLOB選項將會為所有匹配查詢表達式的文件生成一個文件list,並將該list存儲進變量variable里,如果不指定GLOB,就要將所有cpp都列進來了,一般如果我們所有cpp都參與編譯,就用GLOB都包含進來就可以了。ADD_LIBRARY的主要作用就是將指定的源文件生成鏈接文件,然后添加到工程中去,該指令常用的語法如下:
add_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] [source1] [source2] [...])
其中<name>表示庫文件的名字,該庫文件會根據命令里列出的源文件來創建。而STATIC、SHARED和MODULE的作用是指定生成的庫文件的類型。STATIC庫是目標文件的歸檔文件,在鏈接其它目標的時候使用。SHARED庫會被動態鏈接(動態鏈接庫),在運行時會被加載。MODULE庫是一種不會被鏈接到其它目標中的插件,但是可能會在運行時使用dlopen-系列的函數。默認狀態下,庫文件將會在於源文件目錄樹的構建目錄樹的位置被創建,該命令也會在這里被調用。
ADD_LIBRARY (${PROJECT_NAME} SHARED ${base_src})
ADD_LIBRARY (${PROJECT_NAME} SHARED ${base_src})
這里的${PROJECT_NAME}就是工程名,也就是Base,這里$通常用來引用變量,這個語法倒是和vs一樣。base_src就是剛才的源文件列表,由於我的工程都是動態鏈接庫,因此,這里用了SHARED。
INCLUDE_DIRECTORIES用來設置頭文件的搜索目錄,也就是跟vs中的VC++目錄一樣的功能,幾乎每個工程都有這么一句。
值得注意的是,通常我們在windows設置動態鏈接庫的時候,都要設置類或函數的導出符號,而Liunx不需要這么做,通常我們可以用宏進行控制,在vs工程中,默認會定義預編譯宏_WINDOWS,通常拿這個就可以控制windows平台和Linux了。
CMakeLists.txt中ADD_DEFINITIONS(-DBASE_EXPORTS)就是為了在windows平台下設置BASE_EXPORTS這個宏,使其導出符號而設置的。
三、第三方庫設置
我們在做項目的時候通常都會用到很多開源庫,vs的通用做法是將其寫到工程文件中,cmake也一樣,也會寫到CMakeLists.txt文件中,它還有更強大的搜索功能,可以不必指定第三方庫的絕對路徑。正好我的工程Log里就用到了第三方庫Log4cpp,我將演示如何設置它。在Log子項目文件夾下新增CMakeLists.txt,其內容有:
TARGET_LINK_LIBRARIES命令是在本項目中對其他工程的依賴設置的,這里設置其依賴Base工程,這就相當於vs里的工程引用了,CMake根據項目間的依賴設置項目生成順序。
FIND_PACKAGE就是用來發現第三方庫的,它首先會在模塊路徑中尋找Find.cmake,這里就是查找FindLog4cpp.cmake,模塊路徑就是CMAKE_MOULE_PATH指定的那個。
.cmake文件里其實寫的也是cmake語句,你完全可以不用它,自己在CMakeLists.txt里寫,不過寫到它里面會更整潔明了。通常比較流行第三方庫的Find.cmake文件不用自己手寫,你總是能在網上找到它。我將我所有可能用到的第三方庫Find.cmake都放到這里。
IF(Log4cpp_FOUND)
INCLUDE_DIRECTORIES(${Log4cpp_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${Log4cpp_LIBRARY})
ELSE()
MESSAGE(STATUS "CANNOT FIND LOG4CPP LIBRARY")
如果找到了Log4cpp,則Log4cpp_FOUND會賦值為true,它其實是FindLog4cpp.cmake里面的一個變量,同時將Log4cpp_INCLUDE_DIR加入其頭文件搜索路徑,Log4cpp_LIBRARY作為其依賴庫。它倆需要在外部設置。如果找不到MESSAGE會輸出一條錯誤,它也被經常用來打印調試信息,總之是非常有用的。打開FindLog4cpp.cmake看一看:
IF(Log4cpp_FOUND)
INCLUDE_DIRECTORIES(${Log4cpp_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${Log4cpp_LIBRARY})
ELSE()
MESSAGE(STATUS "CANNOT FIND LOG4CPP LIBRARY")
如果找到了Log4cpp,則Log4cpp_FOUND會賦值為true,它其實是FindLog4cpp.cmake里面的一個變量,同時將Log4cpp_INCLUDE_DIR加入其頭文件搜索路徑,Log4cpp_LIBRARY作為其依賴庫。它倆需要在外部設置。如果找不到MESSAGE會輸出一條錯誤,它也被經常用來打印調試信息,總之是非常有用的。打開FindLog4cpp.cmake看一看:
可以看到里面的語法跟外面的是一模一樣的。
四、在VS2017中編譯CMake工程
用過CMake的都知道,在windows上用cmake生成sln時,就會給它設置第三方目錄,也就是給第三節的Log4cpp_INCLUDE_DIR等變量賦值,賦值成功后,可以在工程目錄下生成各個vs版本的sln文件,再編譯它。
而在vs2017中已經支持直接打開CMakeLists.txt了,那么第三方目錄在哪設置,sln又生成在哪里了呢。在根目錄中右擊CMakeLists.txt選擇“配置cmake”,這時在根目錄下會生成CMakeSettings.json文件,CMakeLists.txt里用到的配置都可以寫在這里。
其中,buildRoot就是sln生成目錄了。variables就是用來對CMake中用到的變量進行賦值。這里我把第三方庫的編譯結果,都放在根目錄的third_party文件夾中,這跟我們通常的做法沒什么兩樣。
將變量都設置正確后,CMake工程就可以在vs2017上編譯成功了。其他調試之類的與非CMake工程沒什么區別。
五、在Linux上編譯
當我們在Windows上代碼都弄好了之后,剩下的只是在Linux上編譯而已。Linux對第三方庫的管理比Windows強大的多,常用庫輸入sudo apt-get install就可以安裝了。找不到也沒關系,只需要下載后直接編譯就好,不像windows還要生成sln才能編譯。還以Log4cpp為例,從github上下載好后,鍵入如下命令:
cd log4cpp
mkdir build
cmake ..
make
make install
Log4cpp就安裝完畢了
編譯結果通常都會放到/user/include、/user/local/user之類的文件夾下,所以用FindCMake是能直接找到的。第三方庫全部下載好之后,就進入根目錄文件夾,鍵入類似命令:
cd log4cpp
mkdir build
cmake ..
make
大功告成
————————————————
版權聲明:本文為CSDN博主「神氣愛哥」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qingcaichongchong/article/details/86493146
————————————————
版權聲明:本文為CSDN博主「神氣愛哥」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qingcaichongchong/article/details/86493146