CMake构建静态库与动态库以及使用
CMake构建静态库与动态库
- 一、任务
- 二、准备工作
- 三、编译共享库
- 四、ADD_LIBRARY指令
- 五、编译静态库
- 5.1、SET_TARGET_PROPERTIES指令
- 5.2、GET_TARGET_PROPERTY指令
- 六、动态库版本号
- 七、安装共享库和头文件
- 八、使用外部共享库和头文件
- 8.1、准备工作
- 8.2、引入头文件搜索路径
- 8.3、为 target 添加共享库
- 九、使用外部静态库和头文件
- 十、特殊的环境变量
- 总结
一、任务
用例子的方式通俗易懂地解释CMake构建静态库与动态库的过程。
任务:
- 建立一个静态库和动态库,提供HelloFunc 函数供其他程序编程使用,HelloFunc向终端输出Hello World 字符串。
- 安装头文件与共享库。
- 编写一个程序去使用构建的共享库。
二、准备工作
(1)建立 t3 目录,用于存放本节涉及到的工程。
mkdir t3
(2)建立共享库。
cd t3
mkdir lib
(3)在 t3 目录下建立CMakeLists.txt,内容如下:
PROJECT(HELLOLIB)
ADD_SUBDIRECTORY(lib)
(4)在 lib 目录下建立两个源文件hello.c与hello.h。
hello.c 内容如下:
#include "hello.h"
void hello_func(void)
{printf("Hello World!\n");return;
}
hello.h 内容如下:
#ifndef HELLO_H_
#define HELLO_H_ (1)
#include <stdio.h>
void hello_func(void);
#endif
(5)在 lib 目录下建立CMakeLists.txt,内容如下:
SET(LIBHELLO_SRC hello.c)
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
三、编译共享库
采用out-of-source 编译的方式,建立一个build 目录,在build目录中执行:
mkdir build
cd build
cmake ..
make
这时,就可以在lib 目录得到一个libhello.so,这就是共享库。
如果要指定libhello.so 生成的位置,可以通过在主工程文件CMakeLists.txt 中修改 ADD_SUBDIRECTORY(lib)指令来指定一个编译输出位置或者在lib/CMakeLists.txt 中添加 SET(LIBRARY_OUTPUT_PATH <路径>)来指定一个新的位置。
四、ADD_LIBRARY指令
语法:
ADD_LIBRARY(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL]
source1 source2 ... sourceN)
不需要写全libhello.so,只需要填写hello 即可,cmake 系统会自动生成 libhello.X
类型有三种:
- SHARED,动态库。
- STATIC,静态库。
- MODULE,在使用 dyld 的系统有效,如果不支持dyld,则被当作SHARED 对待。
EXCLUDE_FROM_ALL 参数的意思是这个库不会被默认构建,除非有其他的组件依赖或者手工构建。
五、编译静态库
静态库名字跟动态库名字应该是一致的,只不过后缀是.a 罢了。下面用这个指令再来添加静态库:
ADD_LIBRARY(hello STATIC ${LIBHELLO_SRC})
注意,如果是在上面的编译动态库的基础上添加的上述内容,会发现静态库根本没有被构建,仍然只生成了一个动态库。因为hello 作为一个target 是不能重名的,所以,静态库构建指令无效。如果把上面的hello 修改为hello_static:
ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})
就可以构建一个libhello_static.a 的静态库了。
但是这种结果显示不是想要的,我们需要的是名字相同的静态库和动态库,因为 target 名称是唯一的,所以,肯定不能通过 ADD_LIBRARY 指令来实现了。这时候我们需要用到另外一个指令SET_TARGET_PROPERTIES。
5.1、SET_TARGET_PROPERTIES指令
SET_TARGET_PROPERTIES基本语法:
SET_TARGET_PROPERTIES(target1 target2 ...
PROPERTIES prop1 value1
prop2 value2 ...)
这条指令可以用来设置输出的名称,对于动态库,还可以用来指定动态库版本和 API 版本。
在本例中,需要作的是向lib/CMakeLists.txt 中再添加一条:
SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")
这样,我们就可以同时得到libhello.so和libhello.a 两个库了。
lib/CMakeLists.txt最终的的内容:
SET(LIBHELLO_SRC hello.c)
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})
SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")
5.2、GET_TARGET_PROPERTY指令
与SET_TARGET_PROPERTY对应的指令是GET_TARGET_PROPERTY基本语法为:
GET_TARGET_PROPERTY(VAR target property)
具体用法如下例,向lib/CMakeListst.txt 中添加:
GET_TARGET_PROPERTY(OUTPUT_VALUE hello_static OUTPUT_NAME)MESSAGE(STATUS "This is the hello_static OUTPUT_NAME:"${OUTPUT_VALUE})
如果没有这个属性定义,则返回NOTFOUND。
构建结果会发现,libhello.a 已经构建完成,位于 build/lib 目录中,但是libhello.so 却消失了。这个问题的原因是:cmake 在构建一个新的target 时,会尝试清理掉其他使用这个名字的库,因为,在构建libhello.a 时,就会清理掉libhello.so.
为了回避这个问题,比如再次使用SET_TARGET_PROPERTIES 定义 CLEAN_DIRECT_OUTPUT 属性。
向 lib/CMakeLists.txt 中添加:
SET_TARGET_PROPERTIES(hello PROPERTIES CLEAN_DIRECT_OUTPUT 1)
SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
这时候,我们再次进行构建,会发现build/lib 目录中同时生成了libhello.so 和 libhello.a。
六、动态库版本号
按照规则,动态库是应该包含一个版本号的,我们可以看一下系统的动态库,一般情况是:
libhello.so.1.0
libhello.so ->libhello.so.1
libhello.so.1->libhello.so.1.0
为了实现动态库版本号,需要使用 SET_TARGET_PROPERTIES 指令。
具体使用方法如下:
SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.2 SOVERSION 1)
VERSION 指代动态库版本,SOVERSION 指代 API 版本。
将上述指令加入lib/CMakeLists.txt 中,重新构建,在 build/lib 目录会生成:
libhello.so.1.2 libhello.so.1->libhello.so.1.2 libhello.so ->libhello.so.1
七、安装共享库和头文件
以上面的例子,需要将libhello.a, libhello.so.x 以及 hello.h 安装到系统目录,才能真正让其他人开发使用,在本例中我们将 hello 的共享库安装到< prefix >/lib目录,将hello.h 安装到< prefix >/include/hello 目录。
利用上一篇了解到的INSTALL 指令,向lib/CMakeLists.txt 中添加如下指令:
INSTALL(TARGETS hello hello_static LIBRARY DESTINATION lib ARCHIVE DESTINATION lib)
INSTALL(FILES hello.h DESTINATION include/hello)
注意,静态库要使用ARCHIVE 关键字
通过如下命令安装:
cmake -DCMAKE_INSTALL_PREFIX=/usr ..
make
sudo make install
这样就可以将头文件和共享库安装到系统目录/usr/lib 和/usr/include/hello 中了。
[ 50%] Built target hello
[100%] Built target hello_static
Install the project...
-- Install configuration: ""
-- Installing: /usr/lib/libhello.so.1.2
-- Installing: /usr/lib/libhello.so.1
-- Installing: /usr/lib/libhello.so
-- Installing: /usr/lib/libhello.a
-- Installing: /usr/include/hello/hello.h
如果报错:
CMake Error: cmake_symlink_library: System Error: Operation not supported
CMake Error: cmake_symlink_library: System Error: Operation not supported
make[2]: *** [lib/CMakeFiles/hello_dynamic.dir/build.make:85: lib/libhello.so.1.2] Error 1
make[2]: *** Deleting file 'lib/libhello.so.1.2'
make[1]: *** [CMakeFiles/Makefile2:130: lib/CMakeFiles/hello_dynamic.dir/all] Error 2
make: *** [Makefile:130: all] Error 2
则说明可能是通过hgfs共享的Windows目录下进行make,生成so时需要在纯linux环境运行,比如把t3拷贝到~/t3, 并且先把对应的build目录里面的内容清空,重新执行:
cmake ..
make
八、使用外部共享库和头文件
8.1、准备工作
(1)建立 t4 目录,本节所有资源将存储在t4 目录。
mkdir t4
(2)在t4目录下建立src 目录。
cd t4
mkdir src
(3)src目录下编写源文件main.c,内容如下:
#include "hello.h"
int main(void)
{hello_func();return 0;
}
(4)t4目录下编写工程主文件CMakeLists.txt。
PROJECT(NEWHELLO)
ADD_SUBDIRECTORY(src)
(5)t4/src目录下编写src/CMakeLists.txt。
ADD_EXECUTABLE(main main.c)
8.2、引入头文件搜索路径
准备工作完成后,直接构建是失败的,因为找不到头文件"hello.h"。错误输出为是:
cmake/t4/src/main.c:1:19: error: hello.h: 没有那个文件或目录
为了让我们的工程能够找到hello.h 头文件,需要引入一个新的指令INCLUDE_DIRECTORIES,其完整语法为:
INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)
这条指令可以用来向工程添加多个特定的头文件搜索路径,路径之间用空格分割,如果路径中包含了空格,可以使用双引号将它括起来,默认的行为是追加到当前的头文件搜索路径的后面,可以通过两种方式来进行控制搜索路径添加的方式:
CMAKE_INCLUDE_DIRECTORIES_BEFORE,通过SET 这个cmake 变量为on,可以将添加的头文件搜索路径放在已有路径的前面。
通过AFTER 或者BEFORE 参数,也可以控制是追加还是置前。
现在我们在src/CMakeLists.txt 中添加一个头文件搜索路径,方式很简单,加入:
INCLUDE_DIRECTORIES(/usr/include/hello)
进入build 目录,重新进行构建,这时找不到 hello.h 的错误已经消失,但是出现了一个新的错误:
CMakeFiles/main.dir/main.o:在函数‘main’中:
main.c:(.text+0x5):对‘hello_func’未定义的引用
collect2: error: ld returned 1 exit status
src/CMakeFiles/main.dir/build.make:96: recipe for target 'src/main' failed
make[2]: *** [src/main] Error 1
CMakeFiles/Makefile2:97: recipe for target 'src/CMakeFiles/main.dir/all' failed
make[1]: *** [src/CMakeFiles/main.dir/all] Error 2
Makefile:90: recipe for target 'all' failed
make: *** [all] Error 2
因为我们并没有link 到共享库libhello 上。
8.3、为 target 添加共享库
现在需要完成的任务是将目标文件链接到 libhello,这里我们需要引入两个新的指令:LINK_DIRECTORIES 和TARGET_LINK_LIBRARIES。
LINK_DIRECTORIES 的全部语法是:
LINK_DIRECTORIES(directory1 directory2 ...)
这个指令非常简单,添加非标准的共享库搜索路径,比如,在工程内部同时存在共享库和可执行二进制,在编译时就需要指定一下这些共享库的路径。这个例子中我们没有用到这个指令。
TARGET_LINK_LIBRARIES 的全部语法是:
TARGET_LINK_LIBRARIES(target library1 <debug | optimized> library2 ...)
这个指令可以用来为target 添加需要链接的共享库,本例中是一个可执行文件,但是同样可以用于为自己编写的共享库添加共享库链接。
为了解决我们前面遇到的HelloFunc 未定义错误,需要做的是向 src/CMakeLists.txt 中添加如下指令:
TARGET_LINK_LIBRARIES(main hello)
也可以写成:
TARGET_LINK_LIBRARIES(main libhello.so)
这里的hello指的是前面构建的共享库 libhello.XX。
进入build 目录重新进行构建。
cmake ..
make
这时就得到了一个连接到libhello 的可执行程序main,位于build/src目录,运行 main 的结果是输出:
$ ./main
Hello World!
来看一下main 的链接情况:
$ ldd src/main linux-vdso.so.1 (0x00007ffd531fd000)libhello.so.1 => /usr/lib/libhello.so.1 (0x00007ff212afe000)libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff21270d000)/lib64/ld-linux-x86-64.so.2 (0x00007ff212d00000)
可以清楚的看到main 确实链接了共享库libhello,而且链接的是动态库 libhello.so.1。
九、使用外部静态库和头文件
那如何链接到静态库呢?方法很简单:
将 TARGET_LINK_LIBRRARIES 指令修改为:
TARGET_LINK_LIBRARIES(main libhello.a)
重新构建后再来看一下main 的链接情况:
$ ldd src/main linux-vdso.so.1 (0x00007ffc7a161000)libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff1da80c000)/lib64/ld-linux-x86-64.so.2 (0x00007ff1dabfd000)
说明,main 确实链接到了静态库libhello.a。
十、特殊的环境变量
CMAKE_INCLUDE_PATH 和CMAKE_LIBRARY_PATH。 务必注意,这两个是环境变量而不是cmake 变量。
使用方法是要在bash 中用export 或者在csh 中使用set 命令设置或者 CMAKE_INCLUDE_PATH=/home/include cmake …等方式。
这两个变量主要是用来解决以前autotools 工程中 --extra-include-dir 等参数的支持的。也就是,如果头文件没有存放在常规路径(/usr/include, /usr/local/include 等),则可以通过这些变量就行弥补。
以本例中的hello.h 为例,它存放在/usr/include/hello 目录,所以直接查找肯定是找不到的。
前面我们直接使用了绝对路径INCLUDE_DIRECTORIES(/usr/include/hello)告诉工程这个头文件目录。
为了将程序更智能一点,我们可以使用 CMAKE_INCLUDE_PATH 来进行,使用bash 的方法如下:
export CMAKE_INCLUDE_PATH=/usr/include/hello
然后在头文件中将INCLUDE_DIRECTORIES(/usr/include/hello)替换为:
FIND_PATH(myHeader hello.h)
IF(myHeader)
INCLUDE_DIRECTORIES(${myHeader})
ENDIF(myHeader)
FIND_PATH 用来在指定路径中搜索文件名,比如:
FIND_PATH(myHeader NAMES hello.h PATHS /usr/include /usr/include/hello)
这里我们没有指定路径,但是,cmake 仍然可以帮我们找到hello.h 存放的路径,就是因为我们设置了环境变量CMAKE_INCLUDE_PATH。
如果不使用FIND_PATH,CMAKE_INCLUDE_PATH 变量的设置是没有作用的,不能指望它会直接为编译器命令添加参数-I < CMAKE_INCLUDE_PATH >。
以此为例,CMAKE_LIBRARY_PATH 可以用在 FIND_LIBRARY 中。
同样,因为这些变量直接为FIND_指令所使用,所以所有使用FIND_指令的cmake 模块都会受益。
总结
- 通过ADD_LIBRARY 指令构建动态库和静态库。
- 通过SET_TARGET_PROPERTIES 同时构建同名的动态库和静态库。
- 通过SET_TARGET_PROPERTIES 控制动态库版本。
- 使用INSTALL 指令来安装头文件和动态、静态库。
- 通过INCLUDE_DIRECTORIES 指令加入非标准的头文件搜索路径。
- 通过LINK_DIRECTORIES 指令加入非标准的库文件搜索路径。
- 通过TARGET_LINK_LIBRARIES 为库或可执行二进制加入库链接。
- CMake链接到静态库的方式。
- CMake还有很多高级的话题没有探讨,比如编译条件检查、编译器定义、平台判断、如何跟 pkgconfig 配合使用等等。
- cmake 的使用过程其实就是学习cmake 语言并编写 cmake 程序的过程,既然是“cmake 语言”,自然涉及到变量、语法等。
相关文章:

CMake构建静态库与动态库以及使用
CMake构建静态库与动态库一、任务二、准备工作三、编译共享库四、ADD_LIBRARY指令五、编译静态库5.1、SET_TARGET_PROPERTIES指令5.2、GET_TARGET_PROPERTY指令六、动态库版本号七、安装共享库和头文件八、使用外部共享库和头文件8.1、准备工作8.2、引入头文件搜索路径8.3、为 …...

Linux 系统目录结构
登录系统后,在当前命令窗口下输入命令: ls / 你会看到如下图所示: 树状目录结构: 以下是对这些目录的解释: /bin: bin 是 Binaries (二进制文件) 的缩写, 这个目录存放着最经常使用的命令。 /boot: 这里…...
stable diffusion webui安装与使用(官方超简单教程)
预备依赖 下载miniconda 教程参考:https://blog.csdn.net/weixin_43828245/article/details/124768518安装git 参考教程:https://blog.csdn.net/weixin_46474921/article/details/127091723 下载sd-webui 官网 https://github.com/AUTOMATIC1111/stab…...

机器学习:学习k-近邻(KNN)模型建立、使用和评价
机器学习:学习k-近邻(KNN)模型建立、使用和评价 文章目录机器学习:学习k-近邻(KNN)模型建立、使用和评价一、实验目的二、实验原理三、实验环境四、实验内容五、实验步骤1.数据读取2.数据理解3.数据准备4.算…...
Hive Sampling 抽样函数:Random随机抽样、Block 基于数据块抽样、Bucket table 基于分桶表抽样
Hive Sampling 抽样函数 文章目录Hive Sampling 抽样函数Random随机抽样Block 基于数据块抽样Bucket table 基于分桶表抽样语法在HQL中,可以通过三种方式采样数据:随机采样,存储桶表采样和块采样。Random随机抽样 随机抽样使用rand()函数确保…...
2023年中职网络安全竞赛跨站脚本渗透解析-1(超详细)
跨站脚本渗透 任务环境说明:需求环境可私信博主! 服务器场景:Server2125(关闭链接)服务器场景操作系统:未知访问服务器网站目录1,根据页面信息完成条件,将获取到弹框信息作为flag提交;访问服务器网站目录2,根据页面信息完成条件,将获取到弹框信息作为flag提交;访问服…...

虚拟 DOM 详解
什么是虚拟 dom? 虚拟 dom 本质上就是一个普通的 JS 对象,用于描述视图的界面结构 在vue中,每个组件都有一个render函数,每个render函数都会返回一个虚拟 dom 树,这也就意味着每个组件都对应一棵虚拟 DOM 树 查看虚拟…...
Delphi Http Https 最好的解决方法(一)
当前文章主要解决Delphi调用http、https的常见报错。 开发工具: Delphi XE 10.1 Berlin版本 可能所需的控件包: QDAC 请自行下载。 1. 接口描述 dll_init 接口初始化,程序启动时调用,主要是对工具类实例的创建 dll_post 发送post请求&am…...

Allegro无法打开10度走线命令的原因和解决办法
Allegro无法打开10度走线命令的原因和解决办法 做PCB设计的时候,10度走线也是较为常见的设计方式,Allegro支持10度走线,如下图 需要10度走线的时候,Options只需要勾选Route offset命令即可 但有时options处会看不到10度走线的命令,如下图...

Frequency Domain Model Augmentation for Adversarial Attack
原文:[2207.05382] Frequency Domain Model Augmentation for Adversarial Attack (arxiv.org)代码:https://github.com/yuyang-long/SSA.黑盒攻击替代模型与受攻击模型之间的差距通常较大,表现为攻击性能脆弱。基于同时攻击不同模型可以提高…...

react源码中的协调与调度
requestEventTime 其实在React执行过程中,会有数不清的任务要去执行,但是他们会有一个优先级的判定,假如两个事件的优先级一样,那么React是怎么去判定他们两谁先执行呢? // packages/react-reconciler/src/ReactFibe…...

如何快速、全面、深入地掌握一门编程语言
思考路线 如何快速? 什么样的Demo才能让人觉得你掌握了它? 空 判断:构造一个可以判断所有空的 is_empty 函数 for 循环:i 和 集合迭代两种 时间获取:年/月/日 时分秒 时间戳与时间格式互转 休眠时间函数 字符串处理…...

python五子棋代码最简单的,python五子棋代码画棋盘
大家好,本文将围绕python五子棋代码输赢逻辑判断展开说明,如何用python制作五子棋游戏是一个很多人都想弄明白的事情,想搞清楚python五子棋代码最简单的需要先了解以下几个事情。 1、求解用python 编写五子棋怎样编写判断输赢的函数ÿ…...

C++ 智能指针的原理:auto_ptr、unique_ptr、shared_ptr、weak_ptr
目录一、理解智能指针1.普通指针的使用二、智能指针1.auto_ptr2.unique_ptr3.shared_ptr(1)了解shared_ptr(2)shared_ptr的缺陷4.weak_ptr本文代码在win10的vs2019中通过编译。 一、理解智能指针 1.普通指针的使用 如果程序需要…...
二叉树前中后层次遍历,递归实现
文章目录前序遍历代码\Python代码\C中序遍历代码\Python代码\C后序遍历代码\Python代码\C层序遍历代码\Python代码\C反向层序遍历代码\Python代码\C总结前序遍历 题目链接 前序遍历意思就是按照“根节点-左子树-右子树”的顺序来遍历二叉树,通过递归方法来实现…...

【RA4M2系列开发板GPIO体验2按键控制LED】
【RA4M2系列开发板GPIO体验2按键控制LED】1. 前言2. 配置工程2.1 新建FSP项目2.2 硬件连接以及FSP配置2.2.1 硬件连接2.2.2 FSP配置3. 软件实现3.1 实现的功能3.2 FreeRTOS使用3.2.1 Stack分配函数3.2.2 LED任务3.2.3 Key任务3.3 程序设计3.3.1 设置输出hex文件3.3.2 编译3.3.3…...

初步介绍CUDA中的统一内存
初步介绍CUDA中的统一内存 更多精彩内容: https://www.nvidia.cn/gtc-global/?ncidref-dev-876561 文章目录初步介绍CUDA中的统一内存为此,我向您介绍了统一内存,它可以非常轻松地分配和访问可由系统中任何处理器、CPU 或 GPU 上运行的代码使用的数据。…...

UVM实战--加法器
前言 这里以UVM实战(张强)第二章为基础修改原有的DUT,将DUT修改为加法器,从而修改代码以使得更加深入的了解各个组件的类型和使用。 一. 组件的基本框架 和第二章的平台的主要区别点 (1)有两个transactio…...

Linux系统点亮LED
目录应用层操控硬件的两种方式sysfs 文件系统sysfs 与/sys总结标准接口与非标准接口LED 硬件控制方式编写LED 应用程序在开发板上测试对于一款学习型开发板来说,永远都绕不开LED 这个小小的设备,基本上每块板子都至少会有一颗 LED 小灯,对于我…...

在superset中快速制作报表或仪表盘
在中小型企业,当下需要快速迭代、快速了解运营效果的业务,急需一款开源、好用、能快速迭代生产的报表系统。 老板很关心,BI工程师很关心,同时系统开发人员也同样关心,一个好的技术选型往往能够帮助公司减少很多成本&a…...

React源码阅读-fiber核心构建原理
React源码阅读(2)-fiber核心构建原理 好的,我明白了。您提供的文本主要介绍了 React 源码中 Fiber 核心的构建原理,涵盖了从执行上下文到构建、提交、调度等关键阶段,以及相关的代码实现。 您提出的关联问题也很重要,它们深入探讨…...

《100天精通Python——基础篇 2025 第5天:巩固核心知识,选择题实战演练基础语法》
目录 一、踏上Python之旅二、Python输入与输出三、变量与基本数据类型四、运算符五、流程控制 一、踏上Python之旅 1.想要输出 I Love Python,应该使用()函数。 A.printf() B.print() C.println() D.Print() 在Python中想要在屏幕中输出内容,应该使用print()函数…...
信号电压高,传输稳定性变强,但是传输速率下降?
信号电压高,传输稳定性变强,但是传输速率下降? 一、信号电压升高,传输稳定性变强 1.信号幅度更大,抗噪声能力增强 2.噪声,比如干扰电磁波,串扰等相对于信号幅度比例变小,误码率降低 …...

链游技术破壁:NFT资产确权与Play-to-Earn经济模型实战
链游技术破壁:NFT资产确权与Play-to-Earn经济模型实战 ——从「投机泡沫」到「可持续生态」的技术重构 一、NFT确权技术革新:从链上存证到动态赋权 跨链确权架构 全链互操作协议:采用LayerZero协议实现以太坊装备与Solana土地的跨链组合&…...

【MATLAB去噪算法】基于ICEEMDAN联合小波阈值去噪算法
ICEEMDAN联合小波阈值去噪算法相关文献 (注:目前相关论文较少,应用该套代码可发直接一些水刊) 一、CEEMDAN的局限性 模式残留噪声问题:原始CEEMDAN在计算每个IMF时直接对噪声扰动的信号进行模态分解并平均。 后果&a…...

高精度滚珠导轨在医疗设备中的多元应用场景
在医疗行业不断追求高效、精准与安全的今天,医疗设备的性能优化至关重要。每一个精密部件都像是设备这个庞大“生命体”中的细胞,共同维持着设备的稳定运行。滚珠导轨,这一看似不起眼却功能强大的传动元件,正悄然在医疗设备领域发…...

移动端测试岗位高频面试题及解析
文章目录 一、基础概念二、自动化测试三、性能测试四、专项测试五、安全与稳定性六、高级场景七、实战难题八、其他面题 一、基础概念 移动端测试与Web测试的核心区别? 解析:网络波动(弱网测试)、设备碎片化(机型适配&…...

【国产化适配】如何选择高效合规的安全数据交换系统?
一、安全数据交换系统的核心价值与国产化需求 在数字化转型浪潮中,企业数据流动的频率与规模呈指数级增长,跨网文件传输已成为日常运营的刚需,所以安全数据交换系统也是企业必备的工具。然而,数据泄露事件频发、行业合规要求趋严…...
【Prompt实战】国际翻译小组
本文原创作者:姚瑞南 AI-agent 大模型运营专家/音乐人/野生穿搭model,先后任职于美团、猎聘等中大厂AI训练专家和智能运营专家岗;多年人工智能行业智能产品运营及大模型落地经验,拥有AI外呼方向国家专利与PMP项目管理证书。&#…...

电脑开不了机,主板显示67码解决过程
文章目录 现象分析内存条问题BIOS设置问题其它问题 解决清理内存条金手指所需工具操作步骤注意事项 电脑在运行过程中,显示内存不足,重启电脑却无法启动。 现象 System Initialization 主板风扇是转的,也有灯光显示,插上屏幕&am…...