首页 > 其他分享 >CMake基本使用

CMake基本使用

时间:2023-03-07 13:12:52浏览次数:61  
标签:基本 文件 cmake target ... PROJECT add 使用 CMake

1、cmake

cmake是用于构建、测试和软件打包的跨平台工具

2、优势

  1. 避免硬编码路径
  2. 可在多台计算机上构建一个包
  3. 可做持续集成
  4. 支持不同操作系统
  5. 支持多个编译器
  6. 可使用IDE
  7. 使用库
  8. 描述程序的逻辑结构
  9. 单元测试

3、持续集成

自动化(提交、发布、自动化测试),准确发现集成错误

4、cmake工作原理

image-20230206095728442

5、cmake安装

https://blog.csdn.net/u011231598/article/details/80338941

6、构建和运行

创建src源码文件和build编译文件

image-20230206102032253

进入build目录下,指定版本编译src

cmake -G "MinGW Makefiles" ..\src

不指定版本默认为vs

cmake ..\src

构建:在当前目录下

cmake --build .

image-20230206103356852

7、说明

  • cmake命令不区分大小写,但是变量和参数区分
  • 参数用空格或者分号隔开
  • 使用${VAR}引用变量
  • 引号可加可不加,如果有字符串就必须加

8、概念

  • 目标文件(target):可执行文件(add_eexecutable)、库文件(add_library)
  • 命令(cmake-command):下面要讲的函数
  • 变量(cmake-variable):以CMake_开头
  • 属性(cmake-properties):文件/文件夹都有各自的属性

9、命令

https://cmake.org/cmake/help/latest/

https://cmake.org/cmake/help/latest/manual/cmake-commands.7.html

9.1 project

设置项目名

project(<PROJECT-NAME> [<language-name>...])
project(<PROJECT-NAME>
		[VERSION <major>[.<minor>[].<patch>[.<tweak>]]])
		[LANGUAGES <language-name>...]
		
		
# 项目名会被存储在变量 PROJECT_NAME 和 CMAKE_PROJECT_NAME中
# PROJECT_SOURCE_DIR 等价于 <project-name>_SOURCE_DIR
# 可使用message函数输出
message(${PROJECT_NAME})
message(${PROJECT_SOURCE_DIR})
message(${demo_SOURCE_DIR})

image-20230206104853988

image-20230206105023098

9.2 add_executable

add_executable(<name> [WIN32] [MACOSX_BUNDLE]
               [EXCLUDE_FROM_ALL]
               [source1] [source2 ...])
# <name>为可执行文件的名字,与项目名称无关
# win会生成<name>.exe文件

# 如:
add_executable(demo main.cpp)

9.3 message

message([<mode>] "message text" ...)
# 如:
message(STATUS "${PROJECT_VERSION_MAJOR}")

9.4 set

设置变量

set(<variable> <value>... [PARENT_SCOPE])

# 如:
set(a 1)

设置c++标准

set(CMAKE_CXX_STANDARD 11)

设置输出目录

# 设置exe文件出书目录
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

# 设置存档目标文件的输出目录
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)

image-20230206110055402

9.5 option

定义一个开关

option(<variable> "<help_text>" [value])

# value的值为ON 或者 OFF,默认为OFF
# 如:
option(VERSION_ENABLE "output version" ON)

9.6 configure_file

将输入文件进行替换并生成输出文件

configure_file(<input> <output>
               [NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS |
                FILE_PERMISSIONS <permissions>...]
               [COPYONLY] [ESCAPE_QUOTES] [@ONLY]
               [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])

# 输入文件中的 @VAR@ 或 ${VAR} 的字符串会被替换成这些变量的当前值,未定义则是空字符串

config.h.in

#define PROJECT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define PROJECT_VERSION_MINOR @PROJECT_VERSION_MINOR@

编译后

config.h

#define PROJECT_VERSION_MAJOR 1
#define PROJECT_VERSION_MINOR 0
#cmakedefine VAR
// 会被替换成一下两者之一,取决于VAR是否被设置
#define VAR
#undef VAR

image-20230206150448125

image-20230206150402269

9.7 include_directories

将给定的目录添加到编译器用于搜索包含文件的目录中。

include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])

# 目录会被添加到当前文件的 INCLUDE_DIRECTORIES 属性中
# 当前文件的每一个目标文件的INCLUDE_DIRECTORIES 属性也会添加该目录

9.8 target_include_directories

将包含目录添加到目标。

target_include_directories(<target> [SYSTEM] [AFTER|BEFORE]
  <INTERFACE|PUBLIC|PRIVATE> [items1...]
  [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])

# 目标文件有 INCLUDE_DIRECTORIES 和 INTERFACE_INCLUDE_DIRECTORIES 两个属性
# INCLUDE_DIRECTORIES 对内头文件目录
# INTERFACE_INCLUDE_DIRECTORIES 对外头文件目录

# 包含src目录到目标
target_include_directories(demo PUBLIC "${PROJECT_BINARY_DIR}")
target_include_directories(demo INTERFACE "${PROJECT_BINARY_DIR}")
target_include_directories(demo PUBLIC "${PROJECT_BINARY_DIR}")
INCLUDE_DIRECTORIES INTERFACE_INCLUDE_DIRECTORIES
PRIVATE
INTERFACE
PUBLIC

这是再引入config.h就不会报错了

image-20230206145529693

target_link_libraries(<target> ... <item>... ...)

9.10 add_library

使用指定的源文件将库添加到项目中。

add_library(<name> [STATIC | SHARED | MODULE]
            [EXCLUDE_FROM_ALL]
            [<source>...])
 

10、创建子库

image-20230206170906539

# calc/CMakeLists.txt

# 使用指定的源文件将库添加到项目中。
add_library(addition STATIC add.cpp)
# CMakeLists.txt

# 设置静态文件存放目录
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)

# 添加子目录
add_subdirectory(calc)

# 链接静态文件
target_link_libraries(demo PUBLIC addition)

# 将包含目录到目标
target_include_directories(demo PUBLIC ${PROJECT_SOURCE_DIR}/calc)

# target_link_libraries 这条命令一定得在add_executable后面,不然找不到target(demo)
#include<iostream>
#include "add.h"

int main()
{
    std::cout << "1+2=" << add(1,2)<<std::endl;
    return 0;
}

11、使用外部静态库

libaddition.a为静态库

与src同级目录创建other_lib,将.a和.h文件放进去

# 链接静态文件(要使用绝对路径)
target_link_libraries(demo PUBLIC D:/Desktop/demo/other_li/libaddition.a)

12、使用外部动态库

动态库一定.dll文件一定得与exe文件同目录下

13、实例:Excel

创建目录,包含操作excel的文件

image-20230206184121292

# src/excel/CMakeLists.txt

# 使用指定的源文件将库添加到项目中。
add_library(excel STATIC BasicExcel.cpp)
# 添加子目录
add_subdirectory(excel)
# 链接静态文件
target_link_libraries(demo PUBLIC excel)
# 将包含目录到目标
target_include_directories(demo PUBLIC
                            ${PROJECT_BINARY_DIR}
                            ${PROJECT_SOURCE_DIR}/excel
                            )

案例

//实例化一个表格对象
	BasicExcel e;
	//加载一个文件,
	e.Load("test1.xls");
	//指向"Sheet1"工作簿的指针
	BasicExcelWorksheet* sheet1 = e.GetWorksheet("Sheet1");
    double sum = 0;
	if (sheet1)
	{
		//当前excel的总行数
		size_t maxRows = sheet1->GetTotalRows();
		//当前excel的总列数
		size_t maxCols = sheet1->GetTotalCols();
		//输出当前工作表名称(char),采用unicode编码,没有则返回0.
		cout << "Dimension of " << sheet1->GetAnsiSheetName() <<"(" <<maxRows << "," << maxCols << ")" << endl;
		//制表
		for (size_t c = 0; c < maxCols; ++c)
			printf("%10d", c + 1);
		cout << endl;
		/*
		要想得到EXCEL表格内的值,1、获取指向某行某列的指针类型为BasicExcelCell*
								 2、根据调用的成员函数Type(),查看单元格内的数据类型
								 3、根据数据类型的不同,选择不一样的获取数据的类函数
		*/
		for (size_t r = 0; r < maxRows; ++r)
		{
			printf("%d", r + 1);
			for (size_t c = 0; c < maxCols; ++c)
			{
				//返回指向excel单元格的指针,行如果超过65535或列超过255,则返回00.
				BasicExcelCell* cell = sheet1->Cell(r, c);
				//获取单元格指针内容的类型
				switch (cell->Type())
				{
					//undefined
					case BasicExcelCell::UNDEFINED:
						printf("          ");
						break;
					//int
					case BasicExcelCell::INT:
						printf("%10d", cell->GetInteger());		//获取值
						break;
					//double
					case BasicExcelCell::DOUBLE:
						printf("%10.6lf", cell->GetDouble());	//获取值
						break;
					//string
					case BasicExcelCell::STRING:
						printf("%10s", cell->GetString());		//获取值
						break;
					//wstrig
					case BasicExcelCell::WSTRING:
						wprintf(L"%10s", cell->GetWString());	//获取值
						break;
				}
			}
			std::cout << endl;
		}
		/*计算出第二列数据的总和,并替换单元格第二列最后一行的数据*/
		for (int i = 1; i < maxRows; ++i)
		{
			BasicExcelCell* cell = sheet1->Cell(i, 1);
			sum += cell->GetDouble();
		}
		BasicExcelCell* cell2 = sheet1->Cell(maxRows-1, 1);
		cell2->Set(sum);
		
	}
	std::cout << endl;
	
	//e.Save();
	//将修改的文件保存为"test2.xls"
	e.SaveAs("test2.xls");
	//创建新的工作簿,此时打开的文件中有两个excel工作簿,分别为Sheet1,Sheet2.
	e.New(2);
	//将ANSI编码格式的EXCEL工作表重命名为另一个ANSI名称,成功返回true,失败返回false
	e.RenameWorksheet("Sheet1", "city");
	e.RenameWorksheet("Sheet2", "weather");
	//创建类对象e的另一个工作簿
	BasicExcelWorksheet* sheet2 = e.GetWorksheet("city");

	if (sheet2)
	{
		//声明一个指向单元格块的指针
		BasicExcelCell* cell;
		//表格的表头
		const char *title[4] = { "china", "english", "american", "japan" };
		//向单元格添加表头
		for (size_t c = 0; c < 4; ++c)
		{
			cell = sheet2->Cell(0, c+1);
			cell->SetString(title[c]);
		}
		//向单元格添加列头
		for (size_t r = 1; r < 9; ++r)
			sheet2->Cell(r, 0)->Set((int)r);
		//向表格内添加元素
		double cont = 0.23;
		for (size_t i = 0; i < 4; ++i)
		{
			for (size_t j = 0; j < 8; ++j)
				sheet2->Cell( j + 1, i + 1)->SetDouble(cont++);
		}
	}
	e.SaveAs("text3.xls");
	
	e.Load("text3.xls");
	//得到当前文件内一共有多少工作簿
	size_t maxSheets = e.GetTotalWorkSheets();
	cout << "Total number of worksheets:" << e.GetTotalWorkSheets() << endl;
	//对工作簿进行遍历
	for (size_t i = 0; i < maxSheets; ++i)
	{
		//获取工作簿
		BasicExcelWorksheet* sheet = e.GetWorksheet(i);
		if (sheet)
		{
			//获取最大行列数
			size_t maxRows = sheet->GetTotalRows();
			size_t maxCols = sheet->GetTotalCols();
			cout << "Dimension of " << sheet->GetAnsiSheetName() << "(" << maxRows << "," << maxCols << ")" << endl;

			//列表
			if (maxRows > 0)
			{
				for (size_t c = 0; c < maxCols; ++c)
					printf("%10d", c );
				cout << endl;
			}
			//打印表格内容
			for (size_t r = 0; r < maxRows; ++r)
			{
				for (size_t c = 0; c < maxCols; ++c)
				{
					BasicExcelCell* cell = sheet->Cell(r, c);
					switch (cell->Type())
					{
							//undefined
						case BasicExcelCell::UNDEFINED:
							printf("          ");
							break;
							//int
						case BasicExcelCell::INT:
							printf("%10d", cell->GetInteger());		//获取值
							break;
							//double
						case BasicExcelCell::DOUBLE:
							printf("%10.6lf", cell->GetDouble());	//获取值
							break;
							//string
						case BasicExcelCell::STRING:
							printf("%10s", cell->GetString());		//获取值
							break;
							//wstrig
						case BasicExcelCell::WSTRING:
							wprintf(L"%10s", cell->GetWString());	//获取值
							break;
					}
				}
				cout << endl;
			}
			//将文件以csv格式保存
			if (i == 0)
			{
				ofstream f("text.csv");
				sheet->Print(f, ',', '\0');
				f.close();
			}
		}
		cout << endl;
	}

14、安装

14.1 cmake代码

install(TARGETS <target>DESTINATION <dir>)
install(FILES <file>DESTINATION <dir>)
insta11(PROGRAMS<非目标文件的可执行程序>DESTINATION<dir>)
#如脚本
insta11(DIRECTORY<dir>DESTINATION<dir>)#安装目录

实例

install(TARGETS MathFunctions DESTINATION 1ib)
install(FILES MathFunctions.h DESTINATION include)
instal1(DIRECTORY doc/DESTINATION d)

14.2 命令行

cmake --install.
#安装到默认目录
CMAKE_INSTALL_PREFIX
cmake --install.--prefix <dir>
#安装到指定目录

14.3 实例

CMakeLists.txt
# 安装exe文件
install(TARGETS demo DESTINATION bin)
# 安装外部头文件
# 安装外部静态文件
# 安装外部动态文件

calc/CMakeListx.txt
# 使用指定的源文件将库添加到项目中。
add_library(addition STATIC add.cpp)
add_library(sub SHARED sub.cpp)

install(TARGETS addition DESTINATION lib)
install(FILES add.h DESTINATION include)

image-20230206203723235

image-20230206203859289

标签:基本,文件,cmake,target,...,PROJECT,add,使用,CMake
From: https://www.cnblogs.com/dbai/p/17187720.html

相关文章

  • C# 面向对象 类和对象的声明及使用
    C#面向对象类和对象的声明及使用C#是面向对象的编程语言,对象就是面向对象程序设计的核心。所谓对象就是真实世界中的实体,对象与实体是一一对应的,也就是说现实......
  • 02、CMakeLists.txt基本写法
    cmake_minimum_required(VERSION3.10)#设置c++标准#set(CMAKE_CXX_STANDARD11)#设置输出文件存放目录set(CMAKE_RUNTIME_OUTPUT_DIRECTORY${CMAKE_BINARY_DIR}/......
  • 01、xlwings基本使用
    Xlwings中文官网支持xlx、xlxs格式与其他库对比xlwings逻辑表使用应用->工作簿->工作表->范围应用:一个应用(一个xlwings程序)工作簿(book)工作表(sheet)......
  • C# 字符串(String)的使用
    C#字符串(String)的使用本文主要介绍C#中字符串(String)的基础使用操作和相关方法使用(为变量分配字符串、字符串长度、字符串方法、、字符串连接、字符串格式化......
  • Use CMake notes
    WhayneedtheCMake?如果只是构建一个只有一个main.cpp的小型项目,那么确实不需要CMake,直接GCC、G++编译,或者写个build.sh脚本即可,不需要把简单的问题搞复杂化。$g++......
  • SSM环境下使用PageHelper遇到的问题
    错误示范:1、首先需要导包,我原本导入的版本是4.1.6,pom文件中导入无法下载,可以在projectstructure中手动搜索添加<dependency><groupId>com.github.pagehelper</grou......
  • markdown的使用说明
    目录markdown的使用说明一、标题二、段落1、换行2、分割线三、文字显示1、字体2、上下标四、列表1、无序列表2、有序列表3、任务列表五、区块显示六、代码显示1、行内代码2......
  • 《安富莱嵌入式周报》第305期:超级震撼数码管瀑布,使用OpenAI生成单片机游戏代码的可玩
    往期周报汇总地址:http://www.armbbs.cn/forum.php?mod=forumdisplay&fid=12&filter=typeid&typeid=104 说明:谢谢大家的关注,继续为大家盘点上周精彩内容。 视频版:h......
  • MantisBT中文使用手册(四)—— Issue生命周期与工作流
    IssueIssue的创建方式Issue的生命周期是从它被创建的一刻开始的。创建Issue的方法一般有以下几种:MantisBT的Web界面——也就是用户登录MantisBT后报告Issue的地方。SO......
  • Linux备份与恢复使用技巧
    在日常的Linux系统运维中,备份和恢复是非常重要的操作,能够有效避免数据丢失和系统故障导致的影响。本文将介绍一些关于Linux系统备份和恢复的实用技巧,帮助管理员更好地管理......