当前位置: 首页 > news >正文

如何编写一个CMakeLists.txt文件(由简到难,较详细)

在Linux系统下,经常使用CMakeLists.txt文件来链接、编译C++工程,大部分人clone的代码里都是有CMakeLists.txt文件的,只需要cmake ..make就完事了,但在工作中,你必须要有从无到有编写CMakeLists.txt文件的能力。

一、简单CMakeLists.txt文件的编写

1.先看文件目录

在这里插入图片描述
在repository4文件夹下存在好几个C++相关的文件和一个CMakeLIsts.txt文件,文件清单如下表:

文件(夹)名文件(夹)类型/用途
repository4工程文件夹
calc.h头文件,声明了几个函数定义
add.cpp/div.cpp/mult.cpp/sub.cpp头文件中声明的函数的实现
test_calc.cpp调用前面实现的几个函数
CMakeLists.txt编写此文件,用于此工程的链接和编译

以上除CMakeLists.txt文件以外的文件自己在保证调用、语法、功能正确的前提下随便编写。

2.编写CMakeLists.txt文件

(1)编写简单CMakeLists.txt文件的流程

设置cmake的最低版本要求
指定C++标准
设置项目名称
搜索文件夹中源文件
添加头文件路径
生成可执行文件

(2)编写简单CMakeLists.txt文件

cmake_minimum_required(VERSION 3.16)  #cmake最低版本要求,不得高于你计算机安装的版本set(CMAKE_CXX_STANDARD 11)  #指定C++标准project(test_calculate)  #设置项目名称“test_calculate”aux_source_directory(${PROJECT_SOURCE_DIR} SRC)  #添加源文件到变量SRC中,宏PROJECT_SOURCE_DIR指的是正在编写的CMakeLists.txt文件所在的文件夹include_directories(${PROJECT_SOURCE_DIR})  #制定头文件路径,${}符号是CMake语法中从变量取出变量的值的符号add_executable(test_cacl ${SRC})  #使用源文件生成可执行文件test_cacl,源文件的路径及名称位于SRC变量中

这是非常简单的一个CMakeLists.txt文件,仅用于新手了解cmake的体验装

3.建立build文件夹,运行CMakeLists.txt文件,测试文件是否编写正确

建立build文件夹是为了保证源码文件的整洁,链接、编译生成的文件均在build文件夹下。

mkdir build  #在repository4文件夹下执行此命令生成build文件夹
cd build  #进入build文件夹
cmake ..  #使用CMakeLists.txt文件链接项目
make  #编译项目 生成可执行文件
./test_calc  #在编译正确后,运行生成的可执行文件test_calc

运行截图如下
在这里插入图片描述

4.稍微改进一下,显得整齐点

上面文件夹的内容显得比较凌乱,对其进行整理,整理后的文件目录如下,文件内容不变
在这里插入图片描述
将函数实现的cpp文件放在src目录下,将头文件放在include目录下
对应的CMakeLists.txt文件的内容如下

cmake_minimum_required(VERSION 3.16)set(CMAKE_CXX_STANDARD 11)project(test_calculate)aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC)  #修改include_directories(${PROJECT_SOURCE_DIR}/include)  #修改add_executable(test_cacl ${SRC} test_calc.cpp)  #修改

执行命令不变!

二、编写嵌套CMakeLists.txt文件

1.先看文件目录

在这里插入图片描述

在repository5文件夹下存在好几个C++相关的文件和一个CMakeLIsts.txt文件,文件清单如下表:

文件(夹)名文件夹中的文件文件(夹)类型/用途
repository5以下文件(夹)工程文件夹
build链接、编译产生的文件用于存放链接、编译时产生的文件
includecalc.h / convert.h头文件,声明了几个函数定义
calccalc.cpp / CMakeLists.txt头文件calc.h中声明的函数的实现
convconv.cpp / CMakeLists.txt头文件convert.h中声明的函数的实现
test_calctest_calc.cpp / CMakeLists.txt调用calc.cpp实现的几个函数
test_convtest_conv.cpp / CMakeLists.txt调用conv.cpp实现的几个函数
CMakeLists.txt编写此文件,用于此工程的链接和编译

这些文件总共生成两个可执行文件,一个是计算相关的calc,一个是转换大小写字母的conv,我们需要在实现头文件中声明的那些函数的源文件所在的文件夹调用头文件中函数的测试文件(main函数)所在的文件夹 以及 工程项目repository文件夹中创建CMakeLists.txt文件。
以上除CMakeLists.txt文件以外的文件自己在保证调用、语法、功能正确的前提下随便编写。

2.编写嵌套CMakeLists.txt文件

(1)编写嵌套CMakeLists.txt文件的流程
在这里插入图片描述
(2)编写外层CMakeLists.txt文件

cmake_minimum_required(VERSION 3.16)
set(CMAKE_CXX_STANDARD 11)
project(test)#添加子文件夹
add_subdirectory(calc)
add_subdirectory(conv)
add_subdirectory(test_calc)
add_subdirectory(test_conv)

(3)编写内层CMakeLists.txt文件
a.编写calc文件夹中的CMakeLists.txt文件

cmake_minimum_required(VERSION 3.16)
set(CMAKE_CXX_STANDARD 11)
project(calc)aux_source_directory(./ SRC)  # ./=${PROJECT_SOURCE_DIR},在当前CMakeLists.txt所在文件夹(calc)中搜索源文件,并放置在SRC变量中
include_directories(../include)  #添加头文件路径,../表示上一层目录,../include即在上一层目录下的include中
add_library(calculate STATIC ${SRC})  #取出SRC变量的值,生成一个名为calculate的静态库

b.编写test_calc文件夹中的CMakeLists.txt文件

cmake_minimum_required(VERSION 3.16)
set(CMAKE_CXX_STANDARD 11)
project(calculator)
aux_source_directory(./ SRC)
include_directories(../include)link_libraries(calculate)  #链接生成的静态库
add_executable(calculator ${SRC})  #生成名为calculator的可执行文件

与calc相关的CMakeLists.txt就写好了

c.剩下的两个与conv相关的CMakeLists.txt文件其实与上面两个编写是一样的,只是更改一下相关名称而已,其内容如下:
conv文件夹中的CMakeLists.txt:

cmake_minimum_required(VERSION 3.16)
set(CMAKE_CXX_STANDARD 11)
project(conv)aux_source_directory(./ SRC)
include_directories(../include)
add_library(convert STATIC ${SRC})

test_conv文件夹中的CMakeLists.txt:

cmake_minimum_required(VERSION 3.16)
set(CMAKE_CXX_STANDARD 11)
project(convertor)
aux_source_directory(./ SRC)
include_directories(../include)
link_libraries(convert)
add_executable(convertor ${SRC})

3.在项目文件夹下创建build文件夹,测试刚才编写的CMakeLists.txt文件

mkdir build
cd build
cmake ..
make
./test_conv/convertor

在这里插入图片描述

4. 同样改进一下,指定一下生成的库、可执行文件的存放目录

(1)在外层CMakeLists.txt文件中定义要存放生成的库、可执行文件的变量以及路径

set(LIBPATH ${PROJECT_SOURCE_DIR}/lib)  #设置生成库的路径,并放置在变量LIBPATH中
set(EXEPATH ${PROJECT_SOURCE_DIR}/bin)  #设置可执行文件的路径,并放置在变量EXEPATH中
#文件夹bin和lib会自动生成

(2)在内层CMakeLists.txt文件中使用上面两个全局变量LIBPATHEXEPATH

set(LIBRARY_OUTPUT_PATH ${LIBPATH})  #设置库的生成目录,在calc和conv文件夹下的CMakeLists.txt中添加
link_directories(../lib)  #设置要链接的库的目录,在test_calc和test_conv文件夹下的CMakeLists.txt中添加
set(EXECUTABLE_OUTPUT_PATH ${EXEPATH})  #设置可执行文件的生成目录,在test_calc和test_conv文件夹下的CMakeLists.txt中添加

(3)添加后在当前工程的build路径下执行以下命令来测试CMakeLists.txt文件

cmake ..
make
../bin/convertor  #当前在build文件夹中,bin文件夹和build并列,因此需要../

在这里插入图片描述

三、cmake常用函数

1.基础命令

命令功能备注
#单行注释
#[ [ ] ]块注释
${ }从变量或宏中取出其值例如:${PROJECT_SOURCE_DIR}
cmake_minimum_required(VERSION 3.0)指定使用的 cmake 的最低版本非必须,如果不加可能会有警告
project()定义工程名称,并可指定工程的版本、工程描述、web主页地址、支持的语言如果不需要这些都是可以忽略的,只需要指定出工程名字即可
add_executable(可执行程序名 源文件名称)使用后面的源文件生成可执行程序源文件名可以是一个也可以是多个,如有多个可用空格或;间隔
set(VAR [value]将[value]存入变量VAR中[value]可以是多个,空格或;间隔
set(CMAKE_CXX_STANDARD 11)设置C++的标准CMAKE_CXX_STANDARD是预定义的宏
aux_source_directory(< dir > < variable >)dir:要搜索的目录,variable:将从dir目录下搜索到的源文件列表存储到该变量中
file(GLOB/GLOB_RECURSE 变量名 要搜索的文件路径和文件类型)GLOB: 将指定目录下搜索到的满足条件的所有文件名生成一个列表,并将其存储到变量中,GLOB_RECURSE:递归搜索指定目录,将搜索到的满足条件的文件名生成一个列表,并将其存储到变量中GLOB与GLOB_RECURSE 二选一
include_directories(headpath)添加含头文件路径headpath:头文件路径
add_library(库名称 STATIC/SHARED 源文件1 [源文件2] …)使用源文件生成库STATIC:静态库,SHARED:动态库

2.包含库文件

link_libraries(<static lib> [<static lib>...])

参数1:指定出要链接的第一个静态库的名字,可以是全名 libxxx.a,也可以是掐头(lib)去尾(.a)之后的名字 xxx;
参数2-N:要链接的其它静态库的名字(根据实际情况是否需要);
如果该静态库不是系统提供的(自己制作或者使用第三方提供的静态库)可能出现静态库找不到的情况,此时可以将静态库的路径也指定出来:

link_directories(<lib path>)

在cmake中链接动态库的命令如下:

target_link_libraries(<target> <PRIVATE|PUBLIC|INTERFACE> <item>... [<PRIVATE|PUBLIC|INTERFACE> <item>...]...)

target:指定要加载的库的文件的名字:该文件可能是一个源文件、一个动态库/静态库文件、一个可执行文件
PRIVATE|PUBLIC|INTERFACE:动态库的访问权限,默认为PUBLIC
如果各个动态库之间没有依赖关系,无需做任何设置,三者没有没有区别,一般无需指定,使用默认的 PUBLIC 即可,动态库的链接具有传递性,如果动态库 A 链接了动态库B、C,动态库D链接了动态库A,此时动态库D相当于也链接了动态库B、C,并可以使用动态库B、C中定义的方法。

3.日志

message([STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR] "message to display" ...)

(无) :重要消息
STATUS :非重要消息
WARNING:CMake 警告, 会继续执行
AUTHOR_WARNING:CMake 警告 (dev), 会继续执行
SEND_ERROR:CMake 错误, 继续执行,但是会跳过生成的步骤
FATAL_ERROR:CMake 错误, 终止所有处理过程
例如:

# 输出一般日志信息
message(STATUS "source path: ${PROJECT_SOURCE_DIR}")
# 输出警告信息
message(WARNING "source path: ${PROJECT_SOURCE_DIR}")
# 输出错误信息
message(FATAL_ERROR "source path: ${PROJECT_SOURCE_DIR}")

4.变量操作

命令功能
set(变量名1 ${变量名1} ${变量名2} …)将从第二个参数开始往后所有的字符串进行拼接,结果覆盖写入到第一个参数中
list(APPEND < list> [< element> …])APPEND表示进行数据追加,后边的参数和set就一样了
list(REMOVE_ITEM < list> < value>)从list中移除后面的value
list(LENGTH < list> < outputvariable>)获取 list 的长度,< output variable>:新创建的变量,用于存储列表的长度
list(GET < list> < element index> < output variable>)读取列表中指定索引的的元素,可以指定多个索引
list (JOIN < list> < glue> < output variable>)将列表中的元素用连接符(glue)连接起来组成一个字符串
list(FIND < list> < value> < output variable>)查找列表是否存在指定的元素,若果未找到,返回-1
list(INSERT < list> < element_index> < element> [< element> …])在list中指定的位置插入若干元素
list (PREPEND < list> [< element> …])将元素插入到列表的0索引位置
list (POP_BACK < list> [< out-var>…])将列表中最后元素移除
list (POP_FRONT < list> [< out-var>…])将列表中首元素移除
list (REMOVE_ITEM < list> < value> [< value> …])将指定的元素从列表中移除
list (REMOVE_AT < list> < index> [< index> …])将指定索引的元素从列表中移除
list (REMOVE_DUPLICATES < list>)移除列表中的重复元素
list(REVERSE < list>)列表翻转

列表排序

list (SORT <list> [COMPARE <compare>] [CASE <case>] [ORDER <order>])
/*
COMPARE:指定排序方法。有如下几种值可选:STRING:按照字母顺序进行排序,为默认的排序方法FILE_BASENAME:如果是一系列路径名,会使用basename进行排序NATURAL:使用自然数顺序排序
CASE:指明是否大小写敏感。有如下几种值可选:SENSITIVE: 按照大小写敏感的方式进行排序,为默认值INSENSITIVE:按照大小写不敏感方式进行排序
ORDER:指明排序的顺序。有如下几种值可选:ASCENDING:按照升序排列,为默认值DESCENDING:按照降序排列
*/

5.宏定义

在进行程序测试的时候,我们可以在代码中添加一些宏定义,通过这些宏来控制这些代码是否生效,如下所示:

#include <stdio.h>
#define NUMBER  3int main()
{int a = 10;
#ifdef DEBUGprintf("我是一个程序猿, 我不会爬树...\n");
#endiffor(int i=0; i<NUMBER; ++i){printf("hello, GCC!!!\n");}return 0;
}

在程序的第七行对DEBUG宏进行了判断,如果该宏被定义了,那么第八行就会进行日志输出,如果没有定义这个宏,第八行就相当于被注释掉了,因此最终无法看到日志输入出(上述代码中并没有定义这个宏)。
为了让测试更灵活,我们可以不在代码中定义这个宏,而是在测试的时候去把它定义出来,其中一种方式就是在gcc/g++命令中去指定,如下:

gcc test.c -DDEBUG -o app

在gcc/g++命令中通过参数 -D指定出要定义的宏的名字,这样就相当于在代码中定义了一个宏,其名字DEBUG
在CMake中我们也可以做类似的事情,对应的命令叫做add_definitions():

add_definitions(-D宏名称)//针对上面的例子在对应CMakeLists.txt文件中写这句就等于gcc test.c -DDEBUG -o app
//add_definitions(-DDEBUG)

下面的列表中为大家整理了一些CMake中常用的宏:

功能
PROJECT_SOURCE_DIR使用cmake命令后紧跟的目录,一般是工程的根目录
PROJECT_BINARY_DIR执行cmake命令的目录
CMAKE_CURRENT_SOURCE_DIR当前处理的CMakeLists.txt所在的路径
CMAKE_CURRENT_BINARY_DIRtarget 编译目录
EXECUTABLE_OUTPUT_PATH重新定义目标二进制可执行文件的存放位置
LIBRARY_OUTPUT_PATH重新定义目标链接库文件的存放位置
PROJECT_NAME返回通过PROJECT指令定义的项目名称
CMAKE_BINARY_DIR项目实际构建路径,假设在build目录进行的构建,那么得到的就是这个目录的路径

相关文章:

如何编写一个CMakeLists.txt文件(由简到难,较详细)

在Linux系统下&#xff0c;经常使用CMakeLists.txt文件来链接、编译C工程&#xff0c;大部分人clone的代码里都是有CMakeLists.txt文件的&#xff0c;只需要cmake .. 和make就完事了&#xff0c;但在工作中&#xff0c;你必须要有从无到有编写CMakeLists.txt文件的能力。 一、…...

数据结构----链表

一丶概念 链表又称单链表、链式存储结构&#xff0c;用于存储逻辑关系为“一对一”的数据。 和顺序表不同同&#xff0c;使用链表存储数据&#xff0c;不强制要求数据在内存中集中存储&#xff0c;各个元素可以分散存储在内存中。 二丶特点 特点&#xff1a;内存不连续…...

【Qt】内置对话框

一.Qt内置对话框 Qt 提供了多种可复⽤的对话框类型&#xff0c;即 Qt 标准对话框。Qt标准对话框全部继承于QDialog类。常⽤标准对话框如下&#xff1a; 二.内置对话框分类 1.消息对话框 QMessageBox 1.1 概念 消息对话框是应⽤程序中最常⽤的界⾯元素。消息对话框主要⽤于为…...

excel常规操作

一、去重 IF(COUNTIF($D$1:D2,D2)>1,"",C2) —— D是去重的列 二、不同列匹配 VLOOKUP(A1,E:F,2,0) vlookup(查找值, 查找区域, 返回查找区域的第几列数据, 精确查找输入参数"0"or"false" 或 模糊查找输入参数"1"or"true…...

uniapp webview子页面向父页面发送数据和触发事件,重点在第3条!!!

1、众所周知H5中iframe可以用过postmessage进行&#xff0c;从H5子页面向H5父页面进行通信。方法如下&#xff1a; // 子页面 window.parent.postMessage({ data: 你的消息 }, *);// 父页面 <iframe src"xxxxxxxxxxx"></iframe> window.addEventListene…...

【STM32实物】基于STM32+ESP32+手机APP设计的智能宠物喂食系统实物源码原理图PCB设计文档演示视频——(文末工程资料下载)

基于STM32+ESP32+手机APP设计的智能宠物喂食系统 演示视频 基于STM32+ESP32+手机APP设计的智能宠物喂食系统 摘 要 近年来,宠物在人们生活中越来越不可或缺,给人们带来的陪伴和快乐。然而,由于种种原因,主人不能时刻照顾宠物的饮食,所以宠物喂食装置变得尤为重要。传…...

EMC学习笔记5——辐射骚扰发射

辐射骚扰发射是基本的实验项目&#xff0c;目的是检验设备在工作时有没有产生意外的过强电磁辐射。 例如发电机&#xff0c;在工作时会产生意外的电磁波辐射&#xff0c;因为电子设备中隐藏了一些天线&#xff0c;这些隐藏的天线在辐射电磁波。 一、两种基本的天线结构 如前面…...

深入理解浏览器解析机制和XSS向量编码

基础部分 1.<a href"%6a%61%76%61%73%63%72%69%70%74:%61%6c%65%72%74%28%31%29">aaa</a> <a>标签可以识别&#xff0c;但是解析不了&#xff0c; 是在协议的编码顺序上&#xff0c;先认协议 URL 编码 "javascript:alert(1)" 2.<a …...

winform 大头针实现方法——把窗口钉在最上层

平时我们再使用成熟的软件的时候&#xff0c;会发现有个大头针的功能挺不错的。就是点一下大头针&#xff0c;窗口就会钉住&#xff0c;一直保持在最上面一层&#xff0c;这样可以一边设置参数&#xff0c;一边观察这个窗口里面的变化&#xff0c;比较方便。下面我就来简单实现…...

中间件|day1.Redis

Redis 定义 Redis 是一个开源&#xff08;BSD许可&#xff09;的&#xff0c;内存中的数据结构存储系统&#xff0c;它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构&#xff0c;如 字符串&#xff08;strings&#xff09;&#xff0c; 散列&#xff08;hash…...

PMP到底有什么用?

PMP 就是项目管理证书&#xff0c;全称是项目管理专业人士资格认证&#xff0c;对于一个在项目管理岗位混迹五年的老油条来说&#xff0c;PMP 证书是敲开项目管理岗位的第一块砖&#xff0c;每年考 PMP 的人都很多&#xff0c;要是 PMP 证书没有价值&#xff0c;还会有那么多人…...

apache huidi 时间旅行Time Travel)机制

Apache Hudi(Hadoop Upserts Deletes and Incrementals)是一个数据管理框架,它帮助你高效地管理存储在分布式存储系统(如HDFS或云存储)上的大型数据集。其一个关键特性是“时间旅行”,这允许你在特定时间点查询数据的历史版本。 什么是Apache Hudi中的时间旅行? Apach…...

Python 数据可视化,怎么选出合适数据的图表

数据可视化最佳实践 1. 引言&#xff1a;为什么数据可视化最佳实践很重要 数据可视化是数据分析和决策过程中不可或缺的一部分。通过有效的可视化&#xff0c;复杂的数据可以转化为易于理解的信息&#xff0c;从而帮助观众快速做出正确的判断。然而&#xff0c;糟糕的可视化可…...

c# 元组

文章目录 元组的定义元组的使用示例使用场景创建一个列表 在 C# 中&#xff0c;元组&#xff08;Tuple&#xff09;是一种用于存储多个值的数据结构&#xff0c;它可以方便地将不同类型的多个值打包在一起。元组在 C# 7.0 及更高版本中得到了增强&#xff0c;允许更方便地创建和…...

自定义注解

目录 使用注解定义分布式锁 Aop例子 retention 表示在什么时候可以用&#xff0c;runtime表示在运行期可以用 target表示可以用在哪些上面 inherited表示可以被继承 切点和切面类 重点是 pjp.proceed(args) 这个就是执行目标方法&#xff0c;下面的这一段没啥意思 也可…...

报错:Can‘t find Python executable “python“, you can set the PYTHON env variable

将项目导入vscode,执行npm install命令后&#xff0c;报错了&#xff0c;报错的信息是node-sass安装失败&#xff0c;同时提示需要python环境的错误信息&#xff0c;这是因为安装node-sass失败了&#xff0c;而node-sass依赖于Python环境。 1.报错&#xff1a;Cant find Python…...

C++中的错误处理机制

异常的引出 如过你写过不少的程序的话&#xff0c;相信你应该遇到过一些程序所不能处理的错误而导致程序崩溃的问题吧&#xff0c;比如说&#xff1a;操作野指针&#xff0c;访问空指针&#xff0c;函数的除零错误&#xff0c;数组越界&#xff0c;在栈上开辟空间过大导致栈溢…...

【杂乱笔记】图论

图论 文章目录 图论图的存储与深度、广度遍历基础定义代码实现其他补充 并查集基础定义代码实现 最小生成树基础定义代码实现**Kruskal算法**prim算法 拓扑排序基础定义思路分析代码实现 最短路径基础定义代码实现Dijkstra算法Bellman-Ford算法Floyd算法 图的存储与深度、广度遍…...

pdf文件密码忘记,有办法可以打开pdf文件吗?

为确保PDF文件的重要信息不轻易外泄&#xff0c;我们一般会给pdf文件设置打开密码&#xff0c;确保pdf文件的隐私与安全&#xff0c;但随着时间的推移&#xff0c;让我们遗忘了原本设置的密码&#xff0c;这时我们该怎么办呢&#xff1f; 当大家遇到这种情况时&#xff0c;可能…...

git , nvm 快速下载安装包链接

为了记录地址 &#xff0c; 都是复制大神的 &#xff0c; 可以用&#xff01;&#xff01;&#xff01; nvm 包管理工具 和 git安装包 1. nvm https://www.jianshu.com/p/13c0b3ca7c71 https://blog.csdn.net/i_for/article/details/135060019 https://www.cnblogs.com/Fooo/p…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

springboot 百货中心供应链管理系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;百货中心供应链管理系统被用户普遍使用&#xff0c;为方…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

Python竞赛环境搭建全攻略

Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型&#xff08;算法、数据分析、机器学习等&#xff09;不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...