編譯C/C++文件時,很多時候都是直接使用像 gcc main.c 或者 g++ main.cpp 這樣的命令編譯的。但是代碼文件多了后,這樣編譯就很困難了。這時候 就出現(xiàn)了MakeFile 這個工具。
MakeFile 解決了多個文件編譯難的問題,有了MakeFile,只需要在MakeFile的目錄中 運行一下make 命令, 編譯就會自動完成。但是編寫MakeFile又很啰嗦,于是聰明的程序員們有開發(fā)了一個工具,自動生成MakeFile 文件,cmake 的作用就是自動生成MakeFile。畢竟寫cmake要比寫MakeFile要簡單很多
也許你會說,現(xiàn)在都是用IDE寫代碼,IDE都會自動自動編譯和運行,我還學(xué)這些干啥。但是有時候需要服務(wù)器上編譯項目,或者在沒有IDE的機器上編譯項目,這時候MakeFile就很有用了。其實很多IDE也是使用cmake完成編譯的,比如 clion
cmake 安裝
在linux上可以使用源碼安裝和包管理安裝,一般直接用包管理安裝就好了
Ubuntu和Debian
sudo apt-get install cmake
CentOS
sudo yum install cmake
因為cmake只是生成MakeFile,最終組織編譯的還是MakeFile,所以還有安裝make
make 一般都會預(yù)裝,為了保險,還是裝一下
Ubuntu和Debian
sudo apt-get install make
CentOS
sudo yum install make
cmake基本規(guī)則
cmake 也沒啥神秘的,本質(zhì)上也是根據(jù)一定的規(guī)則自動生成MakeFile的,也是有語法的
# 是注釋符號
預(yù)定義變量
PROJECT_NAME項目名稱
PROJECT_SOURCE_DIR工程的根目錄
PROJECT_BINARY_DIR 執(zhí)行cmake命令的目錄
PROJECT_BINARY_DIR 執(zhí)行cmake命令的目錄
CMAKE_CURRENT_SOURCE_DIR當(dāng)前CMakeLists.txt文件所在目錄
CMAKE_C_FLAGS設(shè)置C編譯選項
CMAKE_CXX_FLAGS設(shè)置C++編譯選項
CMAKE_C_COMPILER設(shè)置C編譯器
CMAKE_CXX_COMPILER設(shè)置C++編譯器
EXECUTABLE_OUTPUT_PATH設(shè)置編譯后可執(zhí)行文件目錄
LIBRARY_OUTPUT_PATH設(shè)置生成的庫文件目錄
常用規(guī)則
cmake_minimum_required(VERSION 3.16) 指令cmake 版本
project(hello_world) 設(shè)置工程名
include_directories(${PROJECT_SOURCE_DIR}/include) 添加頭文件路徑
link_directories(${PROJECT_SOURCE_DIR}/lib) 添加鏈接庫的路徑
add_subdirectory(module)添加 module 子目錄, 此目錄下也要有CMakeLists.txt文件
add_executable(project1 main.c)指定編譯的可執(zhí)行文件
add_library(lib1 SHARED library.c library.h)指定生成的庫文件,SHARED是生成動態(tài)庫,STATIC后生成靜態(tài)庫
add_compile_options() 添加編譯選項
target_link_libraries()指定動態(tài)鏈接庫
install()指定make install的目錄
set(XXXX YYYYYY)用于設(shè)置和修改變量
${XXXX} 使用變量
構(gòu)建一個簡單的項目
只有一個 main.c 文件
CMakeList.txt
cmake_minimum_required(VERSION 3.15)
project(project1 C)
set(CMAKE_C_STANDARD 99)
add_executable(project1 main.c)
main.c
#include <stdio.h>
int main() {
printf("Hello, CMakeList!\n");
return 0;
}
編譯一個debug版本
-
mkdir debug新建debug目錄 -
cd debug進入debug目錄 -
cmake -DCMAKE_BUILD_TYPR=debug ..指定編譯模式為debug -
make生成可執(zhí)行文件
此時會生成project1文件
步驟 3 中 cmake -DCMAKE_BUILD_TYPE=release .. 指定編譯模式為release
構(gòu)建一個生成動態(tài)庫的項目
有兩個文件library.h和library.c
CMakeList.txt
cmake_minimum_required(VERSION 3.15)
project(shared C)
set(CMAKE_C_STANDARD 99)
add_library(shared SHARED library.c library.h)
library.h
int add(int a, int b);
library.c
int add(int a, int b) {
return a + b;
}
生成動態(tài)庫
-
mkdir lib新建lib目錄 -
cd lib進入lib目錄 -
cmake -DCMAKE_BUILD_TYPE=debug ..指定編譯模式為debug -
make生成可執(zhí)行文件
此時會生成libshared.so文件
在第一個項目中使用動態(tài)庫
首先把 libshared.so文件和library.h文件復(fù)制到第一個項目中
修改 CMakeList.txt
cmake_minimum_required(VERSION 3.15)
project(project1 C)
set(CMAKE_C_STANDARD 99)
add_executable(project1 main.c)
target_link_libraries(project1 ${PROJECT_SOURCE_DIR}/libshared.so)#指定動態(tài)庫文件
-
mkdir debug新建debug目錄 -
cd debug進入debug目錄 -
cmake -DCMAKE_BUILD_TYPE=debug ..指定編譯模式為debug -
make生成可執(zhí)行文件
最終目錄如圖

把兩個項目合成一個
能不能在一個項目中生成動態(tài)庫并在這個項目中使用呢,當(dāng)然是可以的。
也就是在這個項目中部分文件編譯成動態(tài)庫 .so 文件, 部分文件編譯成 可執(zhí)行文件
修改 CMakeList.txt
cmake_minimum_required(VERSION 3.13.3)
project(project1 C)
set(CMAKE_C_STANDARD 99)
add_library(shared SHARED library.h library.c)
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)#設(shè)置動態(tài)庫輸出目錄
add_executable(project1 main.c)
target_link_libraries(project1 shared)
-
mkdir debug新建debug目錄 -
cd debug進入debug目錄 -
cmake -DCMAKE_BUILD_TYPE=debug ..指定編譯模式為debug -
make生成可執(zhí)行文件
最終目錄如圖

最后
通過幾個簡單的例子,介紹了一下cmake的基本使用,文中是使用cmake構(gòu)建的C項目,換成C++基本沒什么區(qū)別,就不展示了
cmake的功能遠不止這些,還需要在實戰(zhàn)中多學(xué)習(xí),多總結(jié)
2021-03-06 補充
通過上面的方式可以編譯運行,但是會有一個問題,就是 .so 文件不能更改目錄,一旦動態(tài)庫目錄變了,程序就沒法加載,程序也就沒法運行了。為此又找資料學(xué)習(xí)一番,另寫了一篇,傳送門