一 camake第一列,C編譯為so庫
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
對(duì)應(yīng)的CmakeList文件
cmake_minimum_required(VERSION 3.27)
project(test C)
set(CMAKE_C_STANDARD 11)
add_executable(test main.c)
二 Cmake介紹
2.1?CMake 是一個(gè)跨平臺(tái)的項(xiàng)目構(gòu)建工具,CMake可以生成各種構(gòu)建系統(tǒng)的配置文件,包括Makefile、Visual Studio項(xiàng)目文件、Xcode項(xiàng)目文件等,可以幫助開發(fā)人員簡(jiǎn)化項(xiàng)目的構(gòu)建過程,提高開發(fā)效率
2.2?CMake執(zhí)行流程圖
2.3 Cmake最簡(jiǎn)單且必須的3個(gè)文件,如開頭那個(gè)CmakeLists.txt
- cmake_minimum_required:
- 指定使用的 cmake 的最低版本
- 可選,非必須,如果不加可能會(huì)有警告
cmake_minimum_required(VERSION 3.0)
- project:
- 定義工程名稱,并可指定工程的版本、工程描述、web主頁地址、支持的語言(默認(rèn)情況支持所有語言)
- 如果不需要這些都是可以忽略的,只需要指定出工程名字即可
project(<PROJECT-NAME> [<language-name>...])
#或
project(<PROJECT-NAME>
[VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
[DESCRIPTION <project-description-string>]
[HOMEPAGE_URL <url-string>]
[LANGUAGES <language-name>...])
- ?add_executable:
- 定義工程會(huì)生成一個(gè)可執(zhí)行程序,add_executable(可執(zhí)行程序名 源文件名稱)
- 源文件名可以是一個(gè)也可以是多個(gè),如有多個(gè)可用空格或
;
間隔
# 方式1
add_executable(app add.c div.c main.c mult.c sub.c)
# 方式2
add_executable(app add.c;div.c;main.c;mult.c;sub.c)
三 執(zhí)行Cmake命令編譯C/C++文件
3.1 安裝Cmake,最新版
sudo apt install cmake
安裝失敗錯(cuò)誤解決:
E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?
解決:需要更新apt
$ apt-get update
Reading package lists... Done
E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)
解決:無權(quán)限,切換root用戶
$ su root
Password:
su: Authentication failure
解決:設(shè)置root密碼
$ sudo passwd root
New password:
Retype new password:
passwd: password updated successfully
再次安裝Cmake
# sudo apt install cmake
Reading package lists... Done
3.2 創(chuàng)建項(xiàng)目文件夾,里面包含C文件和CMakeLists.txt?
cmaketest
├── test1.c
├── test2.c
├── main.c
├── CMakeLists.txt
test.h
#ifndef HEAD_H
#define HEAD_H
int add(int a ,int b);
int sub(int a ,int b);
int mult(int a ,int b);
int div(int a ,int b);
#endif
test1.c
#include "test.h"
int add(int a ,int b){
return a+b;
}
int sub(int a ,int b){
return a-b;
}
test2.c
#include "test.h"
int mult(int a ,int b){
return a*b;
}
int div(int a ,int b){
return a/b;
}
mian.c
#include <stdio.h>
#include "test.h"
int main(){
int a=20;
int b=10;
int value1 = add(a,b);
int value2 = sub(a,b);
int value3 = mult(a,b);
int value4 = div(a,b);
printf("a , b is%d,%d\n", a, b);
printf("a + b = %d\n", value1);
printf("a - b = %d\n", value2);
printf("a * b = %d\n", value3);
printf("a / b = %d\n", value4);
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(cmaketest)
add_executable(app test1.c test2.c main.c)
3.3 進(jìn)入項(xiàng)目目錄,執(zhí)行cmake命令,cmaketest
# cd /mnt/d/VSProject/cmaketest
執(zhí)行cmake,注意要加.,表示當(dāng)前目錄
# cmake .
可能會(huì)報(bào)錯(cuò)
root@LAPTOP-G67LH5N6:/mnt/d/VSProject/cmaketest# cmake .
-- The C compiler identification is GNU 11.4.0
-- The CXX compiler identification is unknown
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
CMake Error at CMakeLists.txt:2 (project):
? No CMAKE_CXX_COMPILER could be found.? Tell CMake where to find the compiler by setting either the environment
? variable "CXX" or the CMake cache entry CMAKE_CXX_COMPILER to the full path
? to the compiler, or to the compiler name if it is in the PATH.
需要安裝C++編譯器:
sudo apt-get install build-essential
再次執(zhí)行cmake命令,可以看到這次成功了
root@LAPTOP-G67LH5N6:/mnt/d/VSProject/cmaketest# cmake .
-- The CXX compiler identification is GNU 11.4.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /mnt/d/VSProject/cmaketest?
此時(shí)項(xiàng)目目錄會(huì)增加一些makefile相關(guān)文件
maketest
├── CMakeCache.txt? ? ? ? ? ?# new add file
├── CMakeFiles? ? ? ? ? ? ? ? ? # new add dir
├── cmake_install.cmake ? ?# new add file
├── CMakeLists.txt
├── Makefile? ? ? ? ? ? ? ? ? ? ? ? # new add file
├── test1.c├── test2.c
└── main.c
?3.4 執(zhí)行make命令?
# make
?編譯成功會(huì)出現(xiàn)以下信息:
# make
[ 25%] Building C object CMakeFiles/app.dir/test1.c.o
[ 50%] Building C object CMakeFiles/app.dir/test2.c.o
[ 75%] Building C object CMakeFiles/app.dir/main.c.o
[100%] Linking C executable app
[100%] Built target app
此時(shí)的文件目錄
cmaketest
├── app? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 生成的可執(zhí)行程序
├── CMakeCache.txt? ? ? ? ?# CMake緩存
├── CMakeFiles? ? ? ? ? ? ? ? ?# app.dir里面是生成的so庫
├── cmake_install.cmake
├── CMakeLists.txt
├── main.c
├── Makefile
├── test.h
├── test1.c
└── test2.c
3.5 注意,必須寫入口文件,mian方法入口 ,否則可能出現(xiàn)以下錯(cuò)誤
# make
[ 25%] Building C object CMakeFiles/app.dir/test1.c.o
[ 50%] Building C object CMakeFiles/app.dir/test2.c.o
[ 75%] Building C object CMakeFiles/app.dir/main.c.o
[100%] Linking C executable app
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x1b): undefined reference to `main'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/app.dir/build.make:129: app] Error 1
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/app.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
3.6 注意,mian.c里面最好引用頭部文件,可以避免被多次包含
#ifndef HEAD_H
#define HEAD_H
……(頭文件內(nèi)容)
#endif
否則可能在編譯的時(shí)候出現(xiàn)以下錯(cuò)誤,意思出現(xiàn)多次方法加載,重復(fù)加載
# make
[ 25%] Building C object CMakeFiles/app.dir/test1.c.o
[ 50%] Building C object CMakeFiles/app.dir/test2.c.o
[ 75%] Building C object CMakeFiles/app.dir/main.c.o
[100%] Linking C executable app
/usr/bin/ld: CMakeFiles/app.dir/main.c.o: in function `add':
main.c:(.text+0x0): multiple definition of `add'; CMakeFiles/app.dir/test1.c.o:test1.c:(.text+0x0): first defined here
/usr/bin/ld: CMakeFiles/app.dir/main.c.o: in function `sub':
main.c:(.text+0x18): multiple definition of `sub'; CMakeFiles/app.dir/test1.c.o:test1.c:(.text+0x18): first defined here
/usr/bin/ld: CMakeFiles/app.dir/main.c.o: in function `mult':
main.c:(.text+0x2e): multiple definition of `mult'; CMakeFiles/app.dir/test2.c.o:test2.c:(.text+0x0): first defined here
/usr/bin/ld: CMakeFiles/app.dir/main.c.o: in function `div':
main.c:(.text+0x45): multiple definition of `div'; CMakeFiles/app.dir/test2.c.o:test2.c:(.text+0x17): first defined here
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x1b): undefined reference to `main'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/app.dir/build.make:129: app] Error 1
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/app.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
3.7 上面都在同一個(gè)文件夾,看著亂,我們可以新建一個(gè)文件夾,來放編譯生成的目錄。
cmake 用兩個(gè)..,來切換到源碼目錄編譯
# mkdir build
# cd build
# cmake ..
-- The C compiler identification is GNU 11.4.0
-- The CXX compiler identification is GNU 11.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /mnt/d/VSProject/cmaketest/build
這時(shí)我們的目錄就簡(jiǎn)潔了很多
cmaketest
├── CMakeLists.txt
├── main.c
├── test.h
├── test1.c
├── test2.c
├── build? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # cmake,make后生成的文件夾
├──├── app? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 生成的可執(zhí)行程序
├──├── CMakeCache.txt? ? ? ? ?# CMake緩存
├──├── CMakeFiles? ? ? ? ? ? ? ? ?# app.dir里面是生成的so庫
├──├── cmake_install.cmake
├── ├──Makefile
四 Cmake配置參數(shù)
4.1 定義變量:SET指令
# NAME :變量名
# VALUE:變量值
SET(NAME VALUE)
?這樣我們就可以把上面的那些源文件放在一個(gè)SRC_LIST變量中
# 各個(gè)源文件之間使用空格間隔,有可用分號(hào)隔開
# SRC_LIST 是源文件存儲(chǔ)的變量名
set(SRC_LIST test1.c test2.c main.c)
add_executable(app ${SRC_LIST})
4.2? 其它常用變量
指定C++標(biāo)準(zhǔn),如通過C++標(biāo)準(zhǔn)對(duì)應(yīng)的宏DCMAKE_CXX_STANDARD,指定C++標(biāo)準(zhǔn)為C++11
shell語法
$ g++ *.cpp -std=c++11 -o app
cmake語法
set(CMAKE_CXX_STANDARD 11)
指定輸出路徑,宏?EXECUTABLE_OUTPUT_PATH
# 定義一個(gè)變量用于存儲(chǔ)一個(gè)絕對(duì)路徑
# 從根目錄開始完整路徑-可執(zhí)行程序目錄
set(MYPATH /mnt/d/VSProject/cmaketest/outpath)
#?將拼接好的路徑值設(shè)置給宏
set(EXECUTABLE_OUTPUT_PATH ${MYPATH}/bin)
搜索文件:aux_source_directory命令
# 上面只是簡(jiǎn)單配置,生成可執(zhí)行程序。但只適用于文件少的情況,文件上百個(gè)就不合適了,所以需要通過搜# 索文件配置來簡(jiǎn)化和提高執(zhí)行效率。
# dir:要搜索的目錄
# variable:將從dir目錄下搜索到的源文件列表存儲(chǔ)到該變量中
aux_source_directory(dir variable)
# 示例:
# 設(shè)置源文件路徑變量SOURCE_DIR
set(SOURCE_DIR /mnt/d/VSProject/cmaketest)
# 搜索 src 目錄下的源文件
aux_source_directory(${SOURCE_DIR}/src SRC_LIST)
# 添加程序編譯
add_executable(app ${SRC_LIST})
?搜索文件:file命令
#?GLOB: 將指定目錄下搜索到的滿足條件的所有文件名生成一個(gè)列表,并將其存儲(chǔ)到變量中。
#?GLOB_RECURSE:遞歸搜索指定目錄,將搜索到的滿足條件的文件名生成一個(gè)列表,并將其存儲(chǔ)到變量中
# name:變量名
# path:源文件路徑
file(GLOB/GLOB_RECURSE name path);
# 示例:
set(SOURCE_DIR /mnt/d/VSProject/cmakeList)
file(GLOB MAIN_SRC ${SOURCE_DIR}/src/*.cpp)
file(GLOB MAIN_HEAD ${SOURCE_DIR}/include/*.h)
包含頭文件:include_directories命令
#?path頭文件目錄
include_directories(path)
#?示例
set(SOURCE_DIR /mnt/d/VSProject/cmakeList)
include_directories(${SOURCE_DIR}/include)
4.3上面提到的set用法完整示例
# 最小cmake版本
cmake_minimum_required(VERSION 3.0)
# 項(xiàng)目名字
project(cmaketest)
# C++標(biāo)準(zhǔn)
set(CMAKE_CXX_STANDARD 11)
# 定義輸出路徑
set(MYPATH /mnt/d/VSProject/cmaketest/outpath)
# 輸出路徑
set(EXECUTABLE_OUTPUT_PATH ${MYPATH}/bin/)
# 設(shè)置源文件路徑變量
set(SOURCE_DIR /mnt/d/VSProject/cmaketest)
# 搜索頭文件目錄
include_directories(${SOURCE_DIR}/include)
# 搜索源文件目錄
file(GLOB SRC_LIST ${SOURCE_DIR}/src/*.c)
# 添加執(zhí)行目錄
add_executable(app ${SRC_LIST})
執(zhí)行命令,則會(huì)生成上面目錄的文件
# mkdir build
# cd build
# cmake ..?# make
文件目錄
cmaketest
├── build
├── CMakeLists.txt
├── include
│???└── test.h
└── src
? ? ├── test1.c
? ? ├── test2.
? ? └── main.cpp?
五?編譯靜態(tài),動(dòng)態(tài)庫
5.1 前面操作都是生成的可執(zhí)行程序,把可執(zhí)行程序進(jìn)行安裝打包,可以生成Linux的安裝包程序。但如果我們想要生成三方庫供其它平臺(tái)使用,就要編譯成靜態(tài)(.a),或者動(dòng)態(tài)(.so)庫文件
5.2 生成三方庫只需要在上面CMakeLists.txt基礎(chǔ)上增加下面指令就可以:
把?add_executable (執(zhí)行程序命令)換為 add_library(庫命令)
#?庫名稱,自定義就可以,如mylib
#?庫類型,STATIC(靜態(tài))/ SHARED?(動(dòng)態(tài))
#?源文件,一個(gè)或多個(gè),
add_library(庫名稱? 庫類型? 源文件1 [源文件2] ...)?
# 示例
cmake_minimum_required(VERSION 3.0)
project(cmaketest)
set(SOURCE_DIR /mnt/d/VSProject/cmaketest)
include_directories(${SOURCE_DIR}/include)
file(GLOB SRC_LIST "${SOURCE_DIR}/src/*.c")
add_library(calc STATIC ${SRC_LIST})
5.3 輸出目錄要注意下,根上面不同
EXECUTABLE_OUTPUT_PATH 宏 ,用于靜態(tài)目錄
# 只能用于動(dòng)態(tài)so庫
set(EXECUTABLE_OUTPUT_PATH ${SOURCE_DIR}/lib)
LIBRARY_OUTPUT_PATH?宏 ,用于動(dòng)/靜態(tài)目錄
# 適用于動(dòng)態(tài)庫/靜態(tài)庫路徑
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
示例:
cmake_minimum_required(VERSION 3.0)
project(cmaketest)
# 輸出目錄
set(MYPATH /mnt/d/VSProject/cmaketest/outpath)
set(LIBRARY_OUTPUT_PATH ${MYPATH}/lib)
# 示例:
set(SOURCE_DIR /mnt/d/VSProject/cmaketest)
# 包含頭文件
include_directories(${SOURCE_DIR}/include)
file(GLOB SRC_LIST ${SOURCE_DIR}/src/*.c)
# add_executable(app ${SRC_LIST})
# add_library(app STATIC ${SRC_LIST})
add_library(calc SHARED ${SRC_LIST})
執(zhí)行
# mkdir build
# cd build
# cmake ..?# make
這樣就會(huì)在outpath/lib 目錄下生成libcalc.a文件,動(dòng)態(tài)的話就是libcalc.o文件
$ make
[ 25%] Building C object CMakeFiles/app.dir/src/main.c.o
[ 50%] Building C object CMakeFiles/app.dir/src/test1.c.o
[ 75%] Building C object CMakeFiles/app.dir/src/test2.c.o
[100%] Linking C static library ../outpath/lib/libcalc.a
[100%] Built target calc
5.4 靜態(tài)庫,動(dòng)態(tài)庫的區(qū)別和優(yōu)缺點(diǎn)
靜態(tài)庫
優(yōu)點(diǎn):
- 靜態(tài)庫被打包到應(yīng)用程序中加載速度快
- 發(fā)布程序無需提供靜態(tài)庫,移植方便
缺點(diǎn)
- 相同的庫文件數(shù)據(jù)可能在內(nèi)存中被加載多份, 消耗系統(tǒng)資源,浪費(fèi)內(nèi)存
- 庫文件更新需要重新編譯項(xiàng)目文件, 生成新的可執(zhí)行程序, 浪費(fèi)時(shí)間。
?動(dòng)態(tài)庫
優(yōu)點(diǎn):
- 可實(shí)現(xiàn)不同進(jìn)程間的資源共享
- 動(dòng)態(tài)庫升級(jí)簡(jiǎn)單, 只需要替換庫文件, 無需重新編譯應(yīng)用程序
- 可以自由控制何時(shí)加載動(dòng)態(tài)庫, 不調(diào)用庫函數(shù)動(dòng)態(tài)庫不會(huì)被加載
缺點(diǎn):
- 加載速度比靜態(tài)庫慢,但隨著計(jì)算機(jī)性能的提升可以忽略
- 發(fā)布程序需要提供依賴的動(dòng)態(tài)庫
六 鏈接庫文件
6.1 上面已經(jīng)生成了庫文件,那怎樣用這個(gè)庫呢?這時(shí)候就需要用鏈接指令來加載需要的庫。當(dāng)然鏈接的庫可以是自己的庫,也可以是其它三方提供的庫。
6.2 鏈接靜態(tài)庫?link_libraries 指令
# 參數(shù)是多個(gè)靜態(tài)庫的名字
#?可以是全名 libxxx.a
#?也可以是掐頭去掉lib后的名字,xxx.a
link_libraries(<static lib> <static lib>...)
我們把源碼刪掉,保留頭文件,庫文件和CMakeLists.txt,測(cè)試入口main.cpp也可以保留
cmaketest
├── build
├── CMakeLists.txt
├── include
│? ? ?└── head.h
├── outpath
│? ? ?└──?lib
│?? ? ? ??? ?└── libcalc.a ? ? #靜態(tài)庫的名字
└── src
? ? ? ?└── main.cpp
?CMakeLists修改如下:
cmake_minimum_required(VERSION 3.0)
project(cmaketest)
# 輸出庫文件目錄
set(MYPATH /mnt/d/VSProject/cmaketest/outpath)
# set(LIBRARY_OUTPUT_PATH ${MYPATH}/lib)
# 示例:
set(SOURCE_DIR /mnt/d/VSProject/cmaketest)
# 包含頭文件
include_directories(${SOURCE_DIR}/include)
file(GLOB SRC_LIST ${SOURCE_DIR}/src/*.c)
# 包含靜態(tài)庫路徑
link_directories(${MYPATH}/lib)
# 鏈接靜態(tài)庫
link_libraries(calc)
add_executable(apptest ?${SRC_LIST})
# add_library(app STATIC ${SRC_LIST})
# add_library(app SHARED ${SRC_LIST})
執(zhí)行后可以看到生成執(zhí)行程序apptest成功
$ make
[ 50%] Building C object CMakeFiles/apptest.dir/src/main.c.o
[100%] Linking C executable apptest
[100%] Built target apptest
6.3 鏈接動(dòng)態(tài)庫?target_link_libraries 指令,也可以鏈接靜態(tài)庫
# target:指定要加載動(dòng)態(tài)庫的文件的名字(源文件/動(dòng)態(tài)庫文件/可執(zhí)行文件)
# PRIVATE|PUBLIC|INTERFACE:動(dòng)態(tài)庫的訪問權(quán)限,默認(rèn)為PUBLIC
# 如果各個(gè)動(dòng)態(tài)庫之間沒有依賴關(guān)系,用哪個(gè)權(quán)限都可以
# 動(dòng)態(tài)庫的鏈接具有傳遞性,也可以說繼承性。
# PUBLIC:庫會(huì)暴露出去,三方可以看到全部庫
# PRIVATE:庫僅被link到前面的target中,第三方不能感知你調(diào)了啥庫
# INTERFACE:庫不會(huì)被鏈接到前面的target中,只會(huì)導(dǎo)出符號(hào)
target_link_libraries(
? ? libname
? ? <PRIVATE|PUBLIC|INTERFACE> ...?)
同樣保留動(dòng)態(tài)庫so目錄如下:
cmaketest
├── build
├── CMakeLists.txt
├── include
│? ? ?└── head.h
├── outpath
│? ? ?└──?lib
│?? ? ? ??? ?└── libcalc.so? ? ?# 動(dòng)態(tài)庫的名字
└── src
? ? ? ?└── main.cpp
?CMakeLists修改:?注意程序啟動(dòng)后再去鏈接動(dòng)態(tài)庫
cmake_minimum_required(VERSION 3.0)
project(cmaketest)
# 輸出庫文件目錄
set(MYPATH /mnt/d/VSProject/cmaketest/outpath)
# set(LIBRARY_OUTPUT_PATH ${MYPATH}/lib)
# 示例:
set(SOURCE_DIR /mnt/d/VSProject/cmaketest)
# 包含頭文件
include_directories(${SOURCE_DIR}/include)
file(GLOB SRC_LIST ${SOURCE_DIR}/src/*.c)
# 包含靜態(tài)庫路徑
# link_directories(${MYPATH}/lib)
# 鏈接靜態(tài)庫
# link_libraries(calc)
# 啟動(dòng)程序
add_executable(apptest ${SRC_LIST})
# add_library(app STATIC ${SRC_LIST})
# add_library(app SHARED ${SRC_LIST})
# 程序啟動(dòng)后鏈接動(dòng)態(tài)庫
target_link_libraries(apptest calc)
執(zhí)行make命令,生成可執(zhí)行程序
$ make
[ 50%] Building C object CMakeFiles/apptest.dir/src/main.c.o
[100%] Linking C executable apptest
[100%] Built target apptest
6.4 測(cè)試靜態(tài)和動(dòng)態(tài)庫是否可用
這時(shí)候在build目錄下已經(jīng)生成了一個(gè)可執(zhí)行程序apptest,我們?cè)鯓舆\(yùn)行這個(gè)程序呢
第一步需要給apptest 賦予修改文件的權(quán)限
build$ chmod +x apptest
第二步執(zhí)行" ./ ",來運(yùn)行該程序 ,,可以看到程序能夠正常打印
build$ ./apptest
a , b is20,10
a + b = 30
a - b = 10
a * b = 200
a / b = 2
七 日志 message 命令
7.1 日志用來顯示消息
#?type 日志類型:
#?空:重要消息
#?STATUS :非重要消息
#?WARNING:CMake 警告, 會(huì)繼續(xù)執(zhí)行
#?AUTHOR_WARNING:CMake 警告 (dev), 會(huì)繼續(xù)執(zhí)行
#?SEND_ERROR:CMake 錯(cuò)誤, 繼續(xù)執(zhí)行,但是會(huì)跳過生成的步驟
#?FATAL_ERROR:CMake 錯(cuò)誤, 終止所有處理過程
# message文本消息
message(type message...)
示例:
cmake_minimum_required(VERSION 3.0)
project(cmaketest)
# 輸出一般日志信息
message(STATUS "STATUS Message")
# 輸出警告信息
message(WARNING "WARNING Message")
# 輸出錯(cuò)誤信息
message(FATAL_ERROR "FATAL_ERROR Message")
執(zhí)行cmake指令,生成如下日志
八 List 集合指令操作
8.1 Cmake用法不止上面作用,當(dāng)然也支持多級(jí)嵌套,也支持條件表達(dá)式和循環(huán)表達(dá)式。這里不再細(xì)講,下面說下字符串拼接和List操作相關(guān)用法。
8.2 鏈接字符串
set命令拼接字符串
# 將字符串拼接后賦值給RESULT
set(RESULT ${STRING_1} ${STRING_2} ${STRING_3})
list APPEND 追加字符串
list(APPEND RESULT ${STRING_1} ${STRING_2} ${STRING_3})
8.3?list? REMOVE_ITEM?字符串移除
list(REMOVE_ITEM RESULT ${STRING_1}/main.cpp)
8.4 list??LENGTH 獲取長(zhǎng)度
list(LENGTH ${STRING_1} RESULT )?
8.5 list用法非常多就不一一演示了,下面常用指令
- INSERT? ? ? ? ? ? ? ? ? 增
- REMOVE_ITEM? ? ?刪
- JOIN? ? ? ? ? ? ? ? ? ? ? ?改
- FIND? ? ? ? ? ? ? ? ? ? ? 查
- REVERSE? ? ? ? ? ? ?翻轉(zhuǎn)
- SORT? ? ? ? ? ? ? ? ? ? 排序
- POP_BACK? ? ? ? ? 移除末尾元素
- POP_FRONT? ? ? ? 移除開頭元素
九 宏定義
9.1 自定義宏:add_definitions(-D宏名稱)
cmake_minimum_required(VERSION 3.0)
project(cmaketeat3)
# 自定義 DEBUG 宏
add_definitions(-DDEBUG)
add_executable(app main.c)
main.c文件,?如果定義了DEBUG宏,則會(huì)打印出debug消息...
#include <stdio.h>
int main()
{
int a = 10;
#ifdef DEBUG
printf("debug消息...\n");
#endif
printf("hello,word\n");
return 0;
}
cmake ->?make生成可執(zhí)行程序app
cmaketest3$ cmake .
-- The C compiler identification is GNU 11.4.0
-- The CXX compiler identification is GNU 11.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /mnt/d/VSProject/cmaketest3
$ make
[ 50%] Building C object CMakeFiles/app.dir/main.c.o
[100%] Linking C executable app
[100%] Built target app
執(zhí)行app程序
./app
可以看到走到了定義debug消息的地方
$ ./app
debug消息...
hello,word?
對(duì)應(yīng)C++編譯方式為
cmaketest3$ gcc main.c -DDEBUG -o app
cmaketest3$ ./app
debug消息...
hello,word
C/C++常用的宏
# | 空指令無任何效果 |
#include | 包含源文件 |
#define | 宏定義 |
#undef | 取消已定義的宏 |
#if | 條件判斷,如果給定條件為真,則編譯下面代碼 |
#ifdef | 如果宏已定義,則編譯下面代碼 |
#ifudef | 如果宏沒有定義,則編譯下面代碼 |
#elif | 條件判斷,else if,如果前面條件不為真,當(dāng)前條件為真,則編譯下面代碼 |
#endif | 結(jié)束條件編譯塊,#if.....#elif |
9.2 CMake中的常見預(yù)定義宏
- PROJECT_SOURCE_DIR :使用cmake命令后緊跟的目錄,一般是工程的根目錄
- PROJECT_BINARY_DIR:執(zhí)行cmake命令的目錄
- CMAKE_CURRENT_SOURCE_DIR:當(dāng)前處理的CMakeLists.txt所在的路徑
- CMAKE_CURRENT_BINARY_DIR?:target 編譯目錄
- EXECUTABLE_OUTPUT_PATH: 重新定義目標(biāo)二進(jìn)制可執(zhí)行文件的存放位置
- LIBRARY_OUTPUT_PATH?:重新定義目標(biāo)鏈接庫文件的存放位置
- PROJECT_NAME:返回通過PROJECT指令定義的項(xiàng)目名稱
- CMAKE_BINARY_DIR:項(xiàng)目實(shí)際構(gòu)建路徑,假設(shè)在build目錄進(jìn)行的構(gòu)建,那么得到的就是這個(gè)目錄的路徑
十 調(diào)試庫
10.1 調(diào)試庫需要先生成可執(zhí)行程序
10.1 調(diào)試庫方式
- 通過cmake編譯生成的可執(zhí)行程序
- 當(dāng)然也可以通過C/C++編譯器,來編譯main.c入口文件,生成可執(zhí)行程序
?10.2 我們把庫文件,頭文件和main.c入口文件放在一個(gè)文件夾?
cmaketest2
├── head.h
├── libcalc.a
└── main.c
?編譯測(cè)試程序main.c
# gcc 編譯器
# main.c 測(cè)試入口文件
# -o 輸出可執(zhí)行程序
# app可執(zhí)行程序名字
gcc main.c -o app
但直接執(zhí)行是有問題的:找不到庫里面的方法
$ gcc main.c -o calc
/usr/bin/ld: /tmp/ccG7UGl3.o: in function `main':
main.c:(.text+0x25): undefined reference to `add'
/usr/bin/ld: main.c:(.text+0x37): undefined reference to `sub'
/usr/bin/ld: main.c:(.text+0x49): undefined reference to `mult'
collect2: error: ld returned 1 exit status
所以需要改下,指定庫的絕對(duì)或者相對(duì)路徑?
# 編譯的時(shí)候指定庫信息
# -L: 指定庫所在的目錄(相對(duì)或者絕對(duì)路徑)
# -l: 指定庫的名字, 掐頭(lib)去尾(.a),這里即app
# -L -l, 參數(shù)和參數(shù)值之間可以有空格, 也可以沒有
gcc main.c -o app -L ./ -l calc
執(zhí)行上面指令后就看到目錄多了個(gè)app可執(zhí)行程序文件
cmaketest2
├── app? ? ? ? ? ? #生成的可執(zhí)行程序
├── head.h
├── libcalc.a
└── main.c
執(zhí)行程序
./app
可以看到也可以執(zhí)行成功文章來源:http://www.zghlxwxcb.cn/news/detail-809763.html
cmaketest2$ ./app
a , b is20,10
a + b = 30
a - b = 10
a * b = 200
a / b = 2文章來源地址http://www.zghlxwxcb.cn/news/detail-809763.html
到了這里,關(guān)于Cmake 之Linux庫編譯的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!