日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

cmake 学习笔记(一)

發(fā)布時(shí)間:2023/12/10 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 cmake 学习笔记(一) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
  • 最大的Qt4程序群(KDE4)采用cmake作為構(gòu)建系統(tǒng)
  • Qt4的python綁定(pyside)采用了cmake作為構(gòu)建系統(tǒng)
  • 開源的圖像處理庫 opencv 采用cmake 作為構(gòu)建系統(tǒng)
  • ...

看來不學(xué)習(xí)一下cmake是不行了,一點(diǎn)一點(diǎn)來吧,找個(gè)最簡單的C程序,慢慢復(fù)雜化,試試看:

例子一

單個(gè)源文件 main.c

例子二

==>分解成多個(gè) main.c hello.h hello.c

例子三

==>先生成一個(gè)靜態(tài)庫,鏈接該庫

例子四

==>將源文件放置到不同的目錄

例子五

==>控制生成的程序和庫所在的目錄

例子六

==>使用動態(tài)庫而不是靜態(tài)庫

例子一

一個(gè)經(jīng)典的C程序,如何用cmake來進(jìn)行構(gòu)建程序呢?

//main.c #include <stdio.h> int main() {printf("Hello World!/n");return 0; }

編寫一個(gè) CMakeList.txt 文件(可看做cmake的工程文件):

project(HELLO) set(SRC_LIST main.c) add_executable(hello ${SRC_LIST})

然后,建立一個(gè)任意目錄(比如本目錄下創(chuàng)建一個(gè)build子目錄),在該build目錄下調(diào)用cmake

  • 注意:為了簡單起見,我們從一開始就采用cmake的 out-of-source 方式來構(gòu)建(即生成中間產(chǎn)物與源代碼分離),并始終堅(jiān)持這種方法,這也就是此處為什么單獨(dú)創(chuàng)建一個(gè)目錄,然后在該目錄下執(zhí)行 cmake 的原因
cmake .. -G"NMake Makefiles" nmake

或者

cmake .. -G"MinGW Makefiles" make

即可生成可執(zhí)行程序 hello(.exe)

目錄結(jié)構(gòu)

+ | +--- main.c +--- CMakeList.txt | /--+ build/|+--- hello.exe

cmake 真的不太好用哈,使用cmake的過程,本身也就是一個(gè)編程的過程,只有多練才行。

我們先看看:前面提到的這些都是什么呢?

CMakeList.txt

第一行?project?不是強(qiáng)制性的,但最好始終都加上。這一行會引入兩個(gè)變量

  • HELLO_BINARY_DIR 和 HELLO_SOURCE_DIR

同時(shí),cmake自動定義了兩個(gè)等價(jià)的變量

  • PROJECT_BINARY_DIR?和?PROJECT_SOURCE_DIR

因?yàn)槭莖ut-of-source方式構(gòu)建,所以我們要時(shí)刻區(qū)分這兩個(gè)變量對應(yīng)的目錄

可以通過message來輸出變量的值

message(${PROJECT_SOURCE_DIR})

set?命令用來設(shè)置變量

add_exectuable?告訴工程生成一個(gè)可執(zhí)行文件。

add_library?則告訴生成一個(gè)庫文件。

  • 注意:CMakeList.txt 文件中,命令名字是不區(qū)分大小寫的,而參數(shù)和變量是大小寫相關(guān)的。

cmake命令

cmake 命令后跟一個(gè)路徑(..),用來指出 CMakeList.txt 所在的位置。

由于系統(tǒng)中可能有多套構(gòu)建環(huán)境,我們可以通過-G來制定生成哪種工程文件,通過?cmake?-h?可得到詳細(xì)信息。

要顯示執(zhí)行構(gòu)建過程中詳細(xì)的信息(比如為了得到更詳細(xì)的出錯信息),可以在CMakeList.txt內(nèi)加入:

  • SET( CMAKE_VERBOSE_MAKEFILE on )

或者執(zhí)行make時(shí)

  • $ make VERBOSE=1

或者

  • $ export VERBOSE=1
  • $ make

例子二

一個(gè)源文件的例子一似乎沒什么意思,拆成3個(gè)文件再試試看:

  • hello.h 頭文件
#ifndef DBZHANG_HELLO_ #define DBZHANG_HELLO_ void hello(const char* name); #endif //DBZHANG_HELLO_
  • hello.c
#include <stdio.h> #include "hello.h"void hello(const char * name) {printf ("Hello %s!/n", name); }
  • main.c
#include "hello.h" int main() {hello("World");return 0; }
  • 然后準(zhǔn)備好CMakeList.txt 文件

?

project(HELLO) set(SRC_LIST main.c hello.c) add_executable(hello ${SRC_LIST})

執(zhí)行cmake的過程同上,目錄結(jié)構(gòu)

?

+ | +--- main.c +--- hello.h +--- hello.c +--- CMakeList.txt | /--+ build/|+--- hello.exe

例子很簡單,沒什么可說的。

例子三

接前面的例子,我們將 hello.c 生成一個(gè)庫,然后再使用會怎么樣?

改寫一下前面的CMakeList.txt文件試試:

project(HELLO) set(LIB_SRC hello.c) set(APP_SRC main.c) add_library(libhello ${LIB_SRC}) add_executable(hello ${APP_SRC}) target_link_libraries(hello libhello)

和前面相比,我們添加了一個(gè)新的目標(biāo) libhello,并將其鏈接進(jìn)hello程序

然后想前面一樣,運(yùn)行cmake,得到

+ | +--- main.c +--- hello.h +--- hello.c +--- CMakeList.txt | /--+ build/|+--- hello.exe+--- libhello.lib

里面有一點(diǎn)不爽,對不?

  • 因?yàn)槲业目蓤?zhí)行程序(add_executable)占據(jù)了 hello 這個(gè)名字,所以 add_library 就不能使用這個(gè)名字了
  • 然后,我們?nèi)チ藗€(gè)libhello 的名字,這將導(dǎo)致生成的庫為 libhello.lib(或 liblibhello.a),很不爽
  • 想生成 hello.lib(或libhello.a) 怎么辦?

添加一行

set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")

就可以了

例子四

在前面,我們成功地使用了庫,可是源代碼放在同一個(gè)路徑下,還是不太正規(guī),怎么辦呢?分開放唄

我們期待是這樣一種結(jié)構(gòu)

+ | +--- CMakeList.txt +--+ src/ | | | +--- main.c | /--- CMakeList.txt | +--+ libhello/ | | | +--- hello.h | +--- hello.c | /--- CMakeList.txt | /--+ build/

哇,現(xiàn)在需要3個(gè)CMakeList.txt 文件了,每個(gè)源文件目錄都需要一個(gè),還好,每一個(gè)都不是太復(fù)雜

  • 頂層的CMakeList.txt 文件
project(HELLO) add_subdirectory(src) add_subdirectory(libhello)
  • src 中的 CMakeList.txt 文件
include_directories(${PROJECT_SOURCE_DIR}/libhello) set(APP_SRC main.c) add_executable(hello ${APP_SRC}) target_link_libraries(hello libhello)
  • libhello 中的 CMakeList.txt 文件
set(LIB_SRC hello.c) add_library(libhello ${LIB_SRC}) set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")

恩,和前面一樣,建立一個(gè)build目錄,在其內(nèi)運(yùn)行cmake,然后可以得到

  • build/src/hello.exe
  • build/libhello/hello.lib

回頭看看,這次多了點(diǎn)什么,頂層的 CMakeList.txt 文件中使用 add_subdirectory 告訴cmake去子目錄尋找新的CMakeList.txt 子文件

在 src 的 CMakeList.txt 文件中,新增加了include_directories,用來指明頭文件所在的路徑。

例子五

前面還是有一點(diǎn)不爽:如果想讓可執(zhí)行文件在 bin 目錄,庫文件在 lib 目錄怎么辦?

就像下面顯示的一樣:

+ build/|+--+ bin/| || /--- hello.exe|/--+ lib/|/--- hello.lib
  • 一種辦法:修改頂級的 CMakeList.txt 文件
project(HELLO) add_subdirectory(src bin) add_subdirectory(libhello lib)

不是build中的目錄默認(rèn)和源代碼中結(jié)構(gòu)一樣么,我們可以指定其對應(yīng)的目錄在build中的名字。

這樣一來:build/src 就成了 build/bin 了,可是除了 hello.exe,中間產(chǎn)物也進(jìn)來了。還不是我們最想要的。

  • 另一種方法:不修改頂級的文件,修改其他兩個(gè)文件

src/CMakeList.txt 文件

include_directories(${PROJECT_SOURCE_DIR}/libhello) #link_directories(${PROJECT_BINARY_DIR}/lib) set(APP_SRC main.c) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) add_executable(hello ${APP_SRC}) target_link_libraries(hello libhello)

libhello/CMakeList.txt 文件

set(LIB_SRC hello.c) add_library(libhello ${LIB_SRC}) set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")

例子六

在例子三至五中,我們始終用的靜態(tài)庫,那么用動態(tài)庫應(yīng)該更酷一點(diǎn)吧。 試著寫一下

如果不考慮windows下,這個(gè)例子應(yīng)該是很簡單的,只需要在上個(gè)例子的 libhello/CMakeList.txt 文件中的add_library命令中加入一個(gè)SHARED參數(shù):

add_library(libhello SHARED ${LIB_SRC})

可是,我們既然用cmake了,還是兼顧不同的平臺吧,于是,事情有點(diǎn)復(fù)雜:

  • 修改 hello.h 文件
#ifndef DBZHANG_HELLO_ #define DBZHANG_HELLO_ #if defined _WIN32#if LIBHELLO_BUILD#define LIBHELLO_API __declspec(dllexport)#else#define LIBHELLO_API __declspec(dllimport)#endif #else#define LIBHELLO_API #endif LIBHELLO_API void hello(const char* name); #endif //DBZHANG_HELLO_
  • 修改 libhello/CMakeList.txt 文件
set(LIB_SRC hello.c) add_definitions("-DLIBHELLO_BUILD") add_library(libhello SHARED ${LIB_SRC}) set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")

恩,剩下來的工作就和原來一樣了。

總結(jié)

以上是生活随笔為你收集整理的cmake 学习笔记(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。