前言
在Linux系統如Ubuntu下做C語言編程常見的操作是:寫好代碼,然後使用gcc指令對程序預處理-編譯-彙編-鏈接(其實只用一條指令:gcc -o)。這樣的方法只適合單文件無文件組織的簡單工程。當工程中代碼文件增加且擁有組織結構之後,無可避免就需要去寫makefile。本人之前寫makefile,頭皮發麻,如今趕緊轉正,投向Cmake。
Cmake可以根據工程中CMakeLists.txt的指令自動生成makefile,相對方便易於上手。
準備工作
在Ubuntu下安裝cmake:
sudo apt install cmake
安裝完畢後查看cmake的版本:
cmake --version
可見當前版本是3.5.1,安裝完畢。
單文件工程中使用cmake
新建一個文件夾存放工程,新建一個main.c。內部代碼如下:
#include <stdio.h>
int main() {
printf("hello world!\n");
return 0;
}
顯然是個hello world,程序不重要,接下來在同目錄下新建一個CMakeLists.txt。內容如下:
cmake_minimum_required(VERSION 2.8)#cmake最低版本爲2.8
project(demo)#工程名
add_executable(main main.c)#生成elf文件名爲main,源文件爲main.c
由於沒有文件組織,因此內容較爲簡單。第一句指令爲限定cmake的最低版本爲2.8(本機上cmake版本爲3.5.1)。第二句指令爲該工程的名稱。第三句指令爲工程最終生成的可執行文件名稱爲main,參與編譯的源代碼文件爲main.c。
如上圖所示,工程就準備好了。接下來開始編譯生成可執行文件。在工程目錄處打開終端。輸入:
cmake .
輸入後按回車執行。這裏要注意指令中cmake後面有一個“.”,單點號意爲“當前目錄下”。多文件組織時由於存在子目錄所以是兩個.,這個後面還會提到,先提前注意。
執行完cmake後如上圖所示,生成了一些包含makefile在內的文件。除了makefile之外都是cmake產生的一些中間文件。
隨後在命令行敲入make正式執行makefile:
make
可見目錄中出現了可執行文件,名稱爲main。敲命令行來執行它:
./main
執行成功了。如果程序有修改,則可以使用命令make clean
刪除可執行文件,再使用命令make
重新編譯生成可執行文件。
多文件工程中使用cmake
一個多文件的工程往往是這樣組織的:
文件夾bin:用於存放生成的可執行文件。
文件夾build:用於存放生成的中間文件。
文件夾includes:用於存放所有的頭文件。
文件夾sources:用於存放所有的源文件(.c)。
cmakelists.txt:用於控制全工程的makefile生成。
這裏爲了測試,在工程中添加兩個頭文件,三個c文件。存放目錄如上圖所示。
func1.c代碼如下:
#include "func1.h"
#include <stdio.h>
void DataShow(int data)
{
printf("the input data is:%d \n",data);//打印一個數字
}
func1.h代碼如下:
#ifndef _FUNC1_H_
#define _FUNC1_H_
extern void DataShow(int data);
#endif
func2.c代碼如下:
#include <stdio.h>
#include "func2.h"
void DataAdd(int a,int b)//打印兩個數字之和
{
int c = a+b;
printf("the number is:%d\n",c);
}
func2.h代碼如下:
#ifndef _FUNC2_H_
#define _FUNC2_H_
extern void DataAdd(int a,int b);
#endif // !_FUNC2_H_
main.c代碼如下:
#include <stdio.h>
#include "func1.h"
#include "func2.h"
int main(void)
{
DataAdd(2,2);//打印兩個數字之和
printf("data is:%d\n",5);//打印5
DataShow(5);//打印一個數字
return 0;
}
cmakelists.txt內容如下:
cmake_minimum_required(VERSION 2.8)#cmake最低版本爲2.8
project(demo)#項目名稱
aux_source_directory(sources SRC_LIST)#將源文件夾中的源文件集合定義爲變量
include_directories(includes)#添加頭文件路徑
add_executable(main ${SRC_LIST})#生成elf文件名爲main,源文件在源文件夾中
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)#將工程根目錄下的bin文件夾作爲輸出
命令的前兩句不談了,和之前的一樣。
命令第三句aux_source_directory(sources SRC_LIST)
意爲將sources文件夾裏面的文件集合定義成一個變量,該變量叫SRC_LIST
。今後調用這個變量即爲調用所有sources文件夾裏的源文件。
命令第四句include_directories(includes)
意爲將includes文件夾中的頭文件添加到工程中。
命令第五句本質和單文件工程中的一樣。生成可執行文件的名稱爲main,源文件是變量SRC_LIST
,即sources文件夾中所有的源文件。這裏還需要稍微注意一下,${SRC_LIST}
指SRC_LIST
是個變量,而不是參量,格式需要注意。
命令第六句意爲將輸出的可執行文件定位到工程根目錄下的bin文件夾。參量EXECUTABLE_OUTPUT_PATH
、變量PROJECT_SOURCE_DIR
都是cmake中的預設量,分別意爲“可執行文件保存的路徑”,“工程的根目錄”。
接下來我們需要到build文件夾中執行cmake指令。這樣就可以使得生成的中間文件都保存在build文件夾中。
輸入指令:
cmake ..
由上文可知,由於該工程擁有2級目錄因此需要兩個點號。
如上圖所示,cmake完畢後生成一個makefile,隨後在命令行中進行編譯:
make
注意編譯指令也是在build文件夾執行的,因爲makefile在build文件夾中。
由上圖可見,在bin文件夾下生成了可執行文件main。老辦法,執行它。
看到結果,舒服了。