Cmake 实例学习 一
一. 第一個(gè)簡(jiǎn)單的例子
在一個(gè)目錄下面實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 hello world 程序
使用cmake進(jìn)行構(gòu)建的時(shí)候,每個(gè)目錄下面都要有一個(gè) CMakeLists.txt 的文件
如果是一個(gè)稍微大的工程,有多級(jí)目錄,在上級(jí)目錄中的 CMakeLists.txt 中會(huì)有定義要求編譯子目錄的邏輯
當(dāng)前目錄中定義了一個(gè)main.c 和 CMakeLists.txt 文件,兩個(gè)文件的內(nèi)容分別如下
main.c
#include <stdio.h>
int main()
{printf("hello world!\n");return 0;
}
CMakeLists.txt
project (hello)
set(SRC_LIST main.c)
message(STATUS "this is binary dir" ${HELLO_BINARY_DIR})
message(STATUS "this is source dir" ${HELLO_SOURCE_DIR})
add_executable(hello ${SRC_LIST})
重點(diǎn)解釋 CMakeLists.txt 中的內(nèi)容
project 定義工程名成set 定義一個(gè)變量,把后面的 mian.c 賦值給了 SRC_LIST ,這樣做的好處是,
如果需要編譯多個(gè)文件構(gòu)成同一個(gè)可執(zhí)行程序的時(shí)候,
在后面用到的時(shí)候,不需要每次都寫(xiě)多個(gè)文件,只需要使用這個(gè)變量名就可以了message 打印一些信息,這里可以打印多種信息,上文中需要打印出來(lái)的信息就是一個(gè)狀態(tài)信息
后面可能會(huì)用到的打印信息包括,
SEND_ERROR,產(chǎn)生錯(cuò)誤,生成過(guò)程被跳過(guò)。FATAL_ERROR,立即終止所有 cmake 過(guò)程.等add_executable 添加可執(zhí)行程序,hello 是生成的可執(zhí)行程序名
后面的符號(hào)表示生成這個(gè)可執(zhí)行程序需要依賴的源文件注意其中的變量,使用set定義了變量之后,后面在使用的時(shí)候一般是需要加上 ${} 符號(hào)的
但是在 IF 判斷語(yǔ)句中,如果使用 ${} 判斷指令的話,就是不正確的,
因?yàn)槟莻€(gè)樣子的話,IF 判斷的就是變量本身的內(nèi)容另外注意的是,工程名project中的hello和可執(zhí)行程序名中 add_executable
中的 hello 是沒(méi)有直接關(guān)系的,即兩處的名稱可以不同
二. 第二個(gè)例子,使hello更像一個(gè)工程
本小結(jié)將完成如下工作
1,為工程添加一個(gè)子目錄 src,用來(lái)放置工程源代碼;
2,添加一個(gè)子目錄 doc,用來(lái)放置這個(gè)工程的文檔 hello.txt
3,在工程目錄添加文本文件 COPYRIGHT, README;
4,在工程目錄添加一個(gè) runhello.sh 腳本,用來(lái)調(diào)用 hello 二進(jìn)制
4,將構(gòu)建后的目標(biāo)文件放入構(gòu)建目錄的 bin 子目錄;
5,最終安裝這些文件:將 hello 二進(jìn)制與 runhello.sh 安裝至/usr/bin,將 doc 目錄
的內(nèi)容以及 COPYRIGHT/README 安裝到/usr/share/doc/cmake/t2,將
我們需要在上一節(jié)的基礎(chǔ)之上,將文件改一下
首先新建一個(gè)目錄t2,將上一個(gè)工程中的所有文件添加到這個(gè)文件中
在當(dāng)前目錄下面新建目錄src。這個(gè)src專門(mén)用于存放文件程序的源代碼
把 main.c 移動(dòng)到 src 目錄下面
上文提到每個(gè)目錄下面需要增加CMakeLists.txt文件
所以需要在src目錄下面新建一個(gè)CMakeLists.txt 文件,文件中寫(xiě)入如下內(nèi)容
add_executable(hello main.c)
因?yàn)樵诠こ讨性黾恿俗幽夸?#xff0c;我們需要在相應(yīng)的父目錄中的CMakeLists.txt 中增加相關(guān)的配置
在父目錄下面的CMakeLists.txt 中修改最后的add,改成
add_subdirectory(src bin)
父目錄中 CMakeLists 全文如下
project (hello)
set(SRC_LIST main.c)
message(STATUS "this is binary dir" ${HELLO_BINARY_DIR})
message(STATUS "this is source dir" ${HELLO_SOURCE_DIR})
#add_executable(hello ${SRC_LIST})
add_subdirectory(src bin)
這里解釋一下最后一句
因?yàn)樵黾恿俗幽夸?#xff0c;這里需要將子目錄增加進(jìn)來(lái),并且將子目錄編譯的結(jié)果放到了 bin目錄下面
這里的重點(diǎn)是,將整個(gè)子目錄將入到工程中,從而這個(gè)父目錄和這個(gè)子目錄整體構(gòu)成了一個(gè)工程
另外我們也可以通過(guò)修改內(nèi)置的隱式變量來(lái)指定程序輸出的位置,簡(jiǎn)要如下
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
三 . 添加共享庫(kù)
有了上面的基礎(chǔ),添加動(dòng)態(tài)庫(kù)也是如此的簡(jiǎn)單
創(chuàng)建一個(gè)新的目錄,用于存放新的工程t3
將之前t2的內(nèi)容拷貝到t3中
新建一個(gè)lib目錄,在lib目錄下面創(chuàng)建三個(gè)文件,分別是 hello.c 和 hello.h 和 CMakeLists.txt
hello.c
#include "hello.h"
void HelloFunc()
{printf("hello world\n");
}
hello.h
#ifndef HELLO_H
#define HELLO_H#include <stdio.h>
void HelloFunc();#endif
CMakeLists
set(LIBHELLO_SRC hello.c)
add_library(hello SHARED ${LIBHELLO_SRC})
這里解釋一下子目錄中的定義,其實(shí)很簡(jiǎn)單,就是生成一個(gè)庫(kù)文件,這里hello是庫(kù)文件的名稱 ,SHARED 表示生成的是動(dòng)態(tài)庫(kù),如果要生成靜態(tài)庫(kù),使用的是STATIC,后面表示生成庫(kù)文件需要的源文件是什么
在父目錄中,修改 CMakeLists如下
cmake_minimum_required(VERSION 2.6)
project (hellolib)
#add_executable(hello ${SRC_LIST})
#add_subdirectory(src bin)
add_subdirectory(lib)
父目錄中的CMakeLists就是添加一個(gè)子目錄,子目錄執(zhí)行的任務(wù)在子目錄中會(huì)定義
四. 生成一個(gè)庫(kù)文件,并鏈接他
在同一個(gè)一個(gè)工程中,我們既需要生成一個(gè)庫(kù)文件,又需要鏈接這個(gè)庫(kù)文件
在上面 二 和 三 的基礎(chǔ)之上,即既保留了 src 目錄,又保留了 lib 目錄的基礎(chǔ)之上,
保持 lib 中的CMakeLists不變,需要修改父目錄中的 CMakeLists如下
cmake_minimum_required(VERSION 2.6)
project (hellolib)
#add_executable(hello ${SRC_LIST})
#add_subdirectory(src bin)
add_subdirectory(lib)
add_subdirectory(src bin)
父目錄中實(shí)際只是在 生成 lib 的基礎(chǔ)之上,增加了而一個(gè)新的子目錄 src
進(jìn)入到 src 目錄中,修改源代碼,我們需要在 main.c 中增加頭文件和修改函數(shù),如下所示
#include <stdio.h>
#include "hello.h"
int main()
{HelloFunc();return 0;
}
重點(diǎn)在 src 中的 CMakeLists 的編寫(xiě),這里因?yàn)樾枰溄拥綆?kù)文件,所以需要注意兩個(gè)內(nèi)容,
一個(gè)是頭文件,一個(gè)是庫(kù)文件
src 中 CMakeLists 的書(shū)寫(xiě)如下所示
include_directories("${PROJECT_SOURCE_DIR}/lib")
add_executable(main main.c)
target_link_libraries(main hello)
第一行,增加頭文件的查找目錄,這里使用了 變量 , PROJECT_SOURCE_DIR 是 cmake 的內(nèi)置變量,表示工程的目錄所在位置,加上這個(gè)頭文件目錄的選項(xiàng)之后,程序在編譯的時(shí)候,就會(huì)到這個(gè)目錄下面去尋找頭文件
第二行 不在贅述
第三行 表示,編譯源文件 main 的時(shí)候,需要鏈接的庫(kù)文件,這個(gè)庫(kù)文件就是之前在 lib 中生成的庫(kù)文件 hello
綜上,在一個(gè)程序編譯的時(shí)候,需要使用庫(kù)文件的時(shí)候,需要注意兩個(gè)內(nèi)容,一個(gè)是頭文件,一個(gè)就是庫(kù)文件
五. 使用 cmake 和 程序代碼,決定是否調(diào)用自制庫(kù)文件
在 四 的基礎(chǔ)之上,我們需要改變一些CMakeLists的配置,通過(guò)判斷是否需要一些條件來(lái)執(zhí)行一些函數(shù)
在頂層的CMakeLists中,修改如下
cmake_minimu_required(VERSION 2.6)
project (hellolib)
#add_executable(hello ${SRC_LIST})
#add_subdirectory(src bin)
option(USE_MYLIB "Use my lib" ON)
add_subdirectory(lib)
add_subdirectory(src bin)
此處在中間加了一個(gè)options的選項(xiàng),定義了一個(gè)選項(xiàng)USE_MYLIB 并默認(rèn)為打開(kāi)的
如果需要不想要一些邏輯的話,我們直接可以通過(guò)修改這個(gè) ON 為OFF就可以關(guān)掉一些功能了
在 src 的CMakeLists中需要修改如下
if (USE_MYLIB)add_definitions(-DUSE_MYLIB)include_directories("${PROJECT_SOURCE_DIR}/lib")set(EXTRA_LIBS ${EXTRA_LIBS} hello)
endif (USE_MYLIB)message(STATUS "extra libs: " ${EXTRA_LIBS})
add_executable(main main.c)
target_link_libraries(main ${EXTRA_LIBS})
這里開(kāi)始就是一個(gè)判斷,就是判斷這個(gè) USE_MYLIB 是否為真,注意這里的 USE_MYLIB 不需要加 ${} 如果加上的,就表示取 他的值了
如果這個(gè)判斷為真,就執(zhí)行如下的操作 ,這個(gè)值在頂層的 CMakeLists 中,已經(jīng)定義為 ON了,所以此處會(huì)判斷為真
在這個(gè) if 為真的判斷中,需要加上一個(gè)宏定義,定義了 一個(gè)東西,這個(gè)宏是可以傳遞到代碼中的
此外,如果這個(gè)判斷為真,還是加上需要鏈接的頭文件,和需要鏈接的庫(kù)文件,這里沒(méi)有直接鏈接上庫(kù)文件,而是通過(guò)將庫(kù)文件賦值給了一個(gè)變量,這個(gè)變量是cmake內(nèi)置的變量
最后,編譯這個(gè)程序,如果上面的判斷為真,就會(huì)鏈接到了這個(gè)庫(kù)文件,如果為假,則這個(gè)內(nèi)置變量就是空的,具體是不是cmake內(nèi)置的變量還有待考證
修改了 CMakeLists之后,還需要在代碼中進(jìn)行修改 ,src 中修改之后的代碼如下
#include <stdio.h>
#ifdef USE_MYLIB
#include "hello.h"
#endifint main()
{
#ifdef USE_MYLIBHelloFunc();
#elseprintf("AAA\n");
#endifreturn 0;
}
前面已經(jīng)說(shuō)過(guò),如果在src 中的CMakeLists中的判斷為真,就會(huì)加上一個(gè)宏,這個(gè)宏可以傳遞到代碼里面的,在代碼中,我們就可以通過(guò)判斷這個(gè)宏是否為真的方式,來(lái)決定是否使用自己定義的庫(kù)文件了
總結(jié)
以上是生活随笔為你收集整理的Cmake 实例学习 一的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 元气骑士瓦尔基里之羽怎么获得?
- 下一篇: 急!!!在线求电影名