cmake基础到实战

news2024/11/18 15:41:46

cmake从基础到实站

在这里插入图片描述

cmake官方教程翻译版
CMake Cookbook中文版
cmake 备忘录
需要注意的一点:QT6采用cmake作为编译系统

CMake是一种跨平台编译工具,CMake主要是编写CMakeLists.txt文件,然后通过cmake命令将CMakeLists.txt文件转化为make所需要的Makefile文件,最后用make命令编译源码生成可执行程序或者库文件。

编译四个阶段
1)预处理(Preprocessing)
2)编译(Compilation)
3)汇编(Assemble) -->‘as’
4)链接(Linking) -->‘ld’
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tqpLDN3H-1670820599867)(编译四个阶段.png)]

编译:把高级语言的源文件进行一系列处理,最终得到二进制代码的可执行文件(传说中的binary)

一般情况下,我们只需要知道编译和链接两个阶段即可,编译阶段是将源程序(*.c)转换成为目标代码(一般是obj文件),链接阶段就是把目标代码(obj文件)与调用库函数代码连接起来形成可执行文件(exe文件)。

静态库:链接阶段,库中目标文件所含的所有将被程序使用的函数的机器码,被copy到最终的可执行文件中。有调用的地方,就会有一个完整的拷贝,造成空间的浪费。
动态库:程序编译时并不会链接到目标代码中,而是在程序运行时才被载入。动态内存库只在内存中存在一份拷贝,避免了静态库浪费空间的问题。

c语言编译
c语言在编译过程中会经过预处理(需要头文件)、 编译、汇编、链接(需要库文件),执行的时候还可能有动态链接过程。在编译的时候只需要头文件的声明就可以了,在链接的时候,把已经链接好的.obj和现有的.lib文件进行链接,这时就可以最终生成可执行文件了。
头文件是告诉编译器函数是如何调用如何返回的,所有实现都是分别编译,最后在链接阶段链在一起。

include目录放置头文件
src目录下放置的是.c/.cpp源文件
build目录是用来构建的项目
lib目录用来放置我们生成库文件。

采用外部构建(out-of-source build),而不是内部构建(in-source build)。
外部编译一个最大的好处是,对于原有的工程没有任何影响,所有动作全部发生在编译目录。

基本语法规则:
• 1.cmake变量使用 方 式 取 值 , 但 是 在 I F 控 制 语 句 中 是 直 接 使 用 变 量 名 。 • 2. 环 境 变 量 使 用 {}方式取值,但是在IF控制语句中是直接使用变量名。 • 2.环境变量使用 ,IF使2.使ENV{}方式取值,使用SET(ENV{VAR} VALUE)赋值。
• 3.指令不区分大小写,一般推荐使用大写。
• cmake本身’不提供’任何’搜索库’的便捷方法,所有搜索库并’给变量赋值’的操作必须由’cmake代码’完成
• 指令是大小写无关的,参数和变量是大小写相关的。但是推荐你全部使用大写指令。
可以使用双引号“”将源文件包含起来。处理特别难处理的名字比如fun c.c,则使用SET(SRC_LIST “fun c.c”)可以防止报错。

1. 概述

CMake项目的主要目录存在一个 CMakeLists.txt 文件
我们有两种当时设置编译规则
• 包含源文件的子文件夹包含 CMakeLists.txt 文件,主目录的 CMakeLists.txt 通过 add_subdirectory 添加子目录即可
• 包含源文件的子文件夹未包含 CMakeLists.txt 文件,子目录编译规则体现在主目录的 CMakeLists.txt 文件

2. 编译流程

在 Linux 平台下使用 CMake 构建 C/C++ 工程的流程如下:
• 编写 CMakeLists.txt 规则
• 执行 cmake $PATH 生成 Makefile(PATH 是CMakeLists.txt 所在的顶层目录)
• 执行 make 进行编译
注意一下 Linux 以下几个文件目录知识
• .或者 ./ 代表当前目录
• …或者 …/ 代表上一级目录
…/…或者 …/…/ 代表上上一级目录

3. CMake的两种构建方式

3.1. 内部构建 (in-source build) : 不推荐使用

内部构建会产生很多中间文件(Generated files,编译的中间文件和makefile文件),这些文件并不是我们最终想要的,和工程源代码文件放在一起会显得杂乱无章。
## 内部构建
# 在当前目录下,编译本目录的CMakeLists.txt,生成Makefile和其他文件
$ cmake .
# 执行make命令,生成target
$ make

3.2. 外部构建 (out-of-source build) : 推荐使用

将编译的目录和源代码目录区分开来,放在不同目录中
## 外部构建
# 1. 在当前目录下,创建build文件夹
$ mkdir build
# 2. 进入到build文件夹
$ cd build
# 3. 编译上级目录的CMakeLists.txt,生成Makefile和其他文件
$ cmake …
# 4. 执行make命令,生成target
$ make


## 编译工程 两种方式设置编译规则: 1. 包含源文件的子文件夹包含CMakeLists.txt文件,主目录的CMakeLists.txt通过add_subdirectory添加子目录即可 2. 包含源文件的子文件夹未包含CMakeLists.txt文件,子目录编译规则体现在主目录的CMakeLists.txt中
## 相关命令 • MESSAGE MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] “message to display” …) 向终端输出用户定义的信息或变量的值,SEND_ERROR:产生错误,生成过程被跳过;STATUS:输出前缀为—的信息;FATAL_ERROR:立即终止所有cmake过程

targets
Executable——add_executable、Libraries——add_library都可以算是target

最低版本要求
cmake_minimum_required (VERSION 2.8.7)

项目名称
project (projectname)
项目名称变量存储在PROJECT_NAME里。

该指定隐式引入了两个CMAKE的变量:
_BINARY_DIR,本例中是 projectname_BINARY_DIR(二进制文件保存路径)
_SOURCE_DIR,本例中是 projectname_SOURCE_DIR(源代码路径)

PROJECT_SOURCE_DIR
项目根目录,也就是CmakeLists.txt目录的绝对路径。

cmake变量
PROJECT_SOURCE_DIR:工程的根目录
PROJECT_BINARY_DIR:运行cmake命令的目录,通常为${PROJECT_SOURCE_DIR}/build
PROJECT_NAME:返回通过 project 命令定义的项目名称
CMAKE_CURRENT_SOURCE_DIR:当前处理的 CMakeLists.txt 所在的路径
CMAKE_CURRENT_BINARY_DIR:target 编译目录
CMAKE_CURRENT_LIST_DIR:CMakeLists.txt 的完整路径
EXECUTABLE_OUTPUT_PATH:可执行文件的存放位置
LIBRARY_OUTPUT_PATH:生成库的文件目录

find_package
项目通过该语句找到外部库、程序、文件等。
可以通过以下标准变量找到模块:
XXX_FOUND——如果没有找到则为false
XXX_INCLUDE_DIRS
XXX_LIBRARIES——要link的库,
XXX_DEFINITIONS
XXX_EXECUTABLE
XXX_LIBRARY DIRS

CMAKE_BUILD_TYPE
编译类型,默认为Debug
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_BUILD_TYPE Release)

set
SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])
定义变量(可以定义多个VALUE,如SET(SRC_LIST main.c util.c reactor.c))
set(KEY VALUE)接受两个参数,用来声明变量。在camke语法中使用KEY并不能直接取到VALUE,必须使用${KEY}这种写法来取到VALUE。

include_directories
指定’查找头文件’的搜索路径,它提供了一个’搜索头文件暂时的根目录’,相当于VS工程中设置“包含目录”,避免了在引用头文件时添加很长的路径。
include_directories(directories)
补充: 官网’不推荐’使用INCLUDE_DIRECTORIES

target_include_directories
target_include_directories( [SYSTEM] [AFTER|BEFORE]
<INTERFACE|PUBLIC|PRIVATE> [items1…]
[<INTERFACE|PUBLIC|PRIVATE> [items2…] …])
为指定目标(target)添加搜索路径,指定目标是指通过如add_executable(),add_library()这样的命令生成的。
INTERFACE、PUBLIC、PRIVATE会限制后面包含路径的作用范围,一般用PUBLIC即可;[items1…]即为头文件搜索路径。
target_include_directories 只会为指定目标包含头文件搜索路径。如果想为不同目标设置不同的搜索路径,那么用target_include_directories更合适。
include_directories和target_include_directories关系有点类似VS工程中的“包含目录”和“附加包含目录”区别,一个是全局,一个是针对单个工程而言。
举个栗子:
add_library(${PROJECT_NAME} SHARED Message.cpp)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)

搜集源文件——aux_source_directory
#包含原程序,即把给定目录下的源程序复制给变量DIR_SRC,但是这里一般都把生成的可执行文件放在bin目录中。
aux_source_directory(DIR_SRC ./)
aux_source_directory(src SRC_SUB)//src对应目录里搜索源文件,保存在文件列表SRC_SUB里
aux_source_directory(. SRC_CUR) //在当前目录进行同样操作
aux_source_directory(. SRC) // 定义SRC变量,其值为当前目录下所有的源代码文件

生成可执行程序——add_executable
语法:add_executable( [WIN32] [MACOSX_BUNDLE][EXCLUDE_FROM_ALL] source1 source2 … sourceN)
用于指定从一组源文件 source1 source2 … sourceN 编译出一个可执行文件且命名为 name。
add_executable(变量名 源文件名)
add_executable(helloworld ${DIR_SRC})
executable(nicp_cloud_visualization nicp_cloud_visualization.cpp)

强调: add_executable’不包括’头’(.h)'文件

添加运行库——add_library
生成/添加静态库或者动态库
语法: add_library( [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] source1 [source2 …])
指定生成的库文件名称,会自动加上前缀和后缀
STATIC 生成静态库
SHARED 生成动态链接库
MODULE 在使用dyld的系统有效,若不支持dyld,等同于SHARED;EXCLUDE_FROM_ALL 表示该库不会被默认构建。
例:add_library(${PROJECT_NAME} SHARED library.cpp library.h)
如果指定库类型,默认编译生成的是静态库。

说明1: 每个’add_library’只能生成一个库–>‘静态|动态’,默认是’静态’库
说明2: 一个’.h’头文件对应的’.c|.cpp’可能有多个,这个时候需要’aux_source_directory’的指令–>‘同上’
SET(LIBHELLO_SRC hello.c java.c) -->‘再多就要使用’ -->‘aux_source_directory’
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})

SET_TARGET_PROPERTIES
设置输出的名称,设置动态库的版本和API版本

添加静态/动态库——link_directories
库文件搜索路径,一般用在add_executable之前。假设我们程序用到了在/usr/lib下的一个静态库libmy.a,那就需要添加如下两个命令
#库所在位置
link_directories(/usr/lib)

设置要链接的库——target_link_libraries
#程序编译时候链接库,将’库’和’二进制可执行程序’进行’链接’
语法: target_link_libraries( [item1 [item2 […]]][[debug|optimized|general] ] …)
用于指定 target 链接的依赖项 item1 item2 …。
target_link_libraries(helloworld my)
表示helloworld要连接my,需要需要保证my必须在helloworld之前生成。

TARGET_LINK_LIBRARIES(target lib1 lib2 …)
为target添加需要链接的共享库

target_link_libraries:添加’链接库’;
target_link_libraries(demo Hello) 将’可执行文件’与’Hello连接’成’最终’文件demo
细节: 换句话说’add_executable(demo ${SRC_LIST})‘还不是最终的’demo’,没有经过’链接’的环节
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UIP0Gn7O-1670820599867)(设置要链接的库.png)]

细节: ‘TARGET_LINK_LIBRARIES’要写在’ADD_EXECUTABLE’后面
target_link_libraries里库文件的顺序’符合gcc链接顺序’的规则,即’被依赖的库’放在’依赖它的库’的后面
1)cmake中链接库的顺序是’a依赖b’,那么b放在a的后面。
2)例如’二进制可执行程序test’依赖a库,b库, ‘a库又依赖b 库’, 那么’顺序如下’:
TARGET_LINK_LIBRARIES(test a;b)
备注: 空格或’;'都可以

属性PRIVATE、PUBLIC、INTERFACE使用主要看头文件、源文件是否包含第三方文件头

头文件(.h,.hpp文件)源文件(.cpp文件)属性
INTERFACE
PRIVATE
PUBLIC

link_directories
链接路径,指定动态链接库或静态链接库的搜索路径。也相当于环境变量中增加’LD_LIBRARY_PATH’的路径的作用。该指令的作用’主要’是指定’要链接的库文件(static|dynamic)‘的路径,相当于vs工程的“库目录”。
可以指定’多个路径’,以’空格’分开,
link_directories仅对’其后面’的targets起作用!!!
link_directories(“${PROJECT_SOURCE_DIR}/library”)

add_subdirectory
如果想添加一个子项目或者模块,可以用它进行构建的子目录。
向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制的存放位置
可以包含.h、.c和.cpp文件,这种方式可以直接添加头文件和源文件,不需要通过INCLUDE_DIRECTORIES指定头文件。
语法:add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
add_subdirectory(${OPEN_SOURCES_DIRECTORY}/cpp_redis)

文件操作

  • file APPEND命令
    file(APPEND … )
    用于向文件中追加内容,如果文件不存在,会创建该文件,如果该文件存在不会覆盖文件中的旧内容,将内容追加到文件末尾。
    set(TEST_CONTENT “\nI am coming”)
    file(APPEND ${PROJECT_SOURCE_DIR}/test.cpp ${TEST_CONTENT})

  • file GLOB命令
    file(GLOB [LIST_DIRECTORIES true[false] [RELATIVE ] [CONFIGURE_DEPENDS] [ …])
    主要用于匹配规则在指定的目录内匹配到所需要的文件,并将文件赋值给变量。
    file (GLOB Copy_Files “.qml" ".xml”)
    file (COPY ${Copy_Files} DESTINATION ${CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG})

  • file RENAME命令
    file(RENAME )
    将旧文件重新命名为新名称newname.
    file(RENAME test_2.cpp test.cpp)

  • file MAKE_DIRECTORY命令
    file(MAKE_DIRECTORY [ …])
    用来创建新目录

  • file COPY命令
    file(COPY … DESTINATION


    [FILE_PERMISSIONS …]
    [DIRECTORY_PERMISSIONS … ]
    [NO_SOURCE_PERMISSIONS] [USE_SOURCE_PERMISSIONS]
    [FILES_MATCHING]
    [ [PATTERN | REGEX ]
    [EXCLUDE] [PERMISSIONS … ] ]
    […])
    用于将文件copy到目标目录中

install 命令
将动态库、可执行程序安装到指定目录

检测环境

操作系统CMAKE_SYSTEM_NAME
if(CMAKE_SYSTEM_NAME STREQUAL “Linux”)
message(STATUS “Configuring on/for Linux”)
elseif(CMAKE_SYSTEM_NAME STREQUAL “Darwin”)
message(STATUS “Configuring on/for macOS”)
elseif(CMAKE_SYSTEM_NAME STREQUAL “Windows”)
message(STATUS “Configuring on/for Windows”)
elseif(CMAKE_SYSTEM_NAME STREQUAL “AIX”)
message(STATUS “Configuring on/for IBM AIX”)
else()
message(STATUS “Configuring on/for ${CMAKE_SYSTEM_NAME}”)
endif()

检测处理器体系结构——32位or64位
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
target_compile_definitions(arch-dependent PUBLIC “IS_64_BIT_ARCH”)
message(STATUS “Target is 64 bits”)
else()
target_compile_definitions(arch-dependent PUBLIC “IS_32_BIT_ARCH”)
message(STATUS “Target is 32 bits”)
endif()



文件输出目录设置
注意:设置的时候要放在add_executable、add_library前面
方法一(常用):
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

注:CMAKE_RUNTIME_OUTPUT_DIRECTORY是指定可执行文件的输出目录,CMAKE_LIBRARY_OUTPUT_DIRECTORY是指定动态库或者静态库的输出目录,CMAKE_ARCHIVE_OUTPUT_DIRECTORY用于设置 ARCHIVE 目标的输出路径。

方法二:
set_target_properties( targets…
PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY “${CMAKE_BINARY_DIR}/lib”
LIBRARY_OUTPUT_DIRECTORY “${CMAKE_BINARY_DIR}/lib”
RUNTIME_OUTPUT_DIRECTORY “${CMAKE_BINARY_DIR}/bin”
)

方法三:
# set output directories for all builds (Debug, Release, etc.)
foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} )
string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG )
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} KaTeX parse error: Expected group after '_' at position 65: …UTPUT_DIRECTORY_̲{OUTPUTCONFIG} ${CMAKE_SOURCE_DIR}/lib )
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_SOURCE_DIR}/bin )
endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES )

常用变量

| 变量| 含义 |
| ---- | ---- | ---- |
| PROJECT_NAME |工程名|
| CMAKE_CURRENT_LIST_DIR |表示正在处理的CMakeLists.txt 文件的所在的目录的绝对路径(2.8.3 以及以后版本才支持)|
| CMAKE_ARCHIVE_OUTPUT_DIRECTORY |静、动态库的lib文件存放位置,|
| CMAKE_LIBRARY_OUTPUT_DIRECTORY |?|
| CMAKE_RUNTIME_OUTPUT_DIRECTORY |设置可执行程序、动态库dll的存储目录|
| CMAKE_SOURCE_DIR |程顶层目录所在路径|
| CMAKE_CURRENT_SOURCE_DIR |当前CMakeLists.txt所在的路径,建议使用CURRENT_SOURCE,不建议使用SOURCE_DIR,因为如果主工程目录改变了,SOURCE_DIR也就会改变,很容易造成编译错误|
| CMAKE_BINARY_DIR |工程编译时的路径|
| EXECUTABLE_OUTPUT_PATH |可执行文件.exe的输出路径|
| LIBRARY_OUTPUT_PATH |静、动态库lib、dll文件的输出路径|

include_directories 和target_include_directories的区别
target_include_directories() 的功能完全可以使用 include_directories() 实现。但是我还是建议使用 target_include_directories()。
target_include_directories为指定目标(target)添加搜索路径,指定目标是指通过如add_executable(),add_library()这样的命令生成的。
target_include_directories 只会为指定目标包含头文件搜索路径。如果想为不同目标设置不同的搜索路径,那么用target_include_directories更合适。
include_directories(header-dir) 是一个全局包含,针对的是所有target(而target_include_directorie只针对一个target),会向下传递。什么意思呢?就是说如果某个目录的 CMakeLists.txt 中使用了该指令,其下所有的子目录默认也包含了header-dir 目录,会增加搜索时间。
当然了,在最终子目录的 CMakeLists.txt 文件中,使用 include_directories() 和 target_include_directories() 的效果是相同的。
每一个目录都是一个模块,目录内部应将对外和对内的头文件进行区分,由模块的调用者决定模块是否被传递(PRIVATE,INTERFACE,PUBLIC)。

么用target_include_directories更合适。
include_directories(header-dir) 是一个全局包含,针对的是所有target(而target_include_directorie只针对一个target),会向下传递。什么意思呢?就是说如果某个目录的 CMakeLists.txt 中使用了该指令,其下所有的子目录默认也包含了header-dir 目录,会增加搜索时间。
当然了,在最终子目录的 CMakeLists.txt 文件中,使用 include_directories() 和 target_include_directories() 的效果是相同的。
每一个目录都是一个模块,目录内部应将对外和对内的头文件进行区分,由模块的调用者决定模块是否被传递(PRIVATE,INTERFACE,PUBLIC)。

cmake从基础到实站

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8iBhaX5T-1670820641306)(許芳宜.jpg)]

cmake官方教程翻译版
CMake Cookbook中文版
cmake 备忘录
需要注意的一点:QT6采用cmake作为编译系统

CMake是一种跨平台编译工具,CMake主要是编写CMakeLists.txt文件,然后通过cmake命令将CMakeLists.txt文件转化为make所需要的Makefile文件,最后用make命令编译源码生成可执行程序或者库文件。

编译四个阶段
1)预处理(Preprocessing)
2)编译(Compilation)
3)汇编(Assemble) -->‘as’
4)链接(Linking) -->‘ld’
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3y88JtMa-1670820641307)(编译四个阶段.png)]

编译:把高级语言的源文件进行一系列处理,最终得到二进制代码的可执行文件(传说中的binary)

一般情况下,我们只需要知道编译和链接两个阶段即可,编译阶段是将源程序(*.c)转换成为目标代码(一般是obj文件),链接阶段就是把目标代码(obj文件)与调用库函数代码连接起来形成可执行文件(exe文件)。

静态库:链接阶段,库中目标文件所含的所有将被程序使用的函数的机器码,被copy到最终的可执行文件中。有调用的地方,就会有一个完整的拷贝,造成空间的浪费。
动态库:程序编译时并不会链接到目标代码中,而是在程序运行时才被载入。动态内存库只在内存中存在一份拷贝,避免了静态库浪费空间的问题。

c语言编译
c语言在编译过程中会经过预处理(需要头文件)、 编译、汇编、链接(需要库文件),执行的时候还可能有动态链接过程。在编译的时候只需要头文件的声明就可以了,在链接的时候,把已经链接好的.obj和现有的.lib文件进行链接,这时就可以最终生成可执行文件了。
头文件是告诉编译器函数是如何调用如何返回的,所有实现都是分别编译,最后在链接阶段链在一起。

include目录放置头文件
src目录下放置的是.c/.cpp源文件
build目录是用来构建的项目
lib目录用来放置我们生成库文件。

采用外部构建(out-of-source build),而不是内部构建(in-source build)。
外部编译一个最大的好处是,对于原有的工程没有任何影响,所有动作全部发生在编译目录。

基本语法规则:
• 1.cmake变量使用 方 式 取 值 , 但 是 在 I F 控 制 语 句 中 是 直 接 使 用 变 量 名 。 • 2. 环 境 变 量 使 用 {}方式取值,但是在IF控制语句中是直接使用变量名。 • 2.环境变量使用 ,IF使2.使ENV{}方式取值,使用SET(ENV{VAR} VALUE)赋值。
• 3.指令不区分大小写,一般推荐使用大写。
• cmake本身’不提供’任何’搜索库’的便捷方法,所有搜索库并’给变量赋值’的操作必须由’cmake代码’完成
• 指令是大小写无关的,参数和变量是大小写相关的。但是推荐你全部使用大写指令。
可以使用双引号“”将源文件包含起来。处理特别难处理的名字比如fun c.c,则使用SET(SRC_LIST “fun c.c”)可以防止报错。

1. 概述

CMake项目的主要目录存在一个 CMakeLists.txt 文件
我们有两种当时设置编译规则
• 包含源文件的子文件夹包含 CMakeLists.txt 文件,主目录的 CMakeLists.txt 通过 add_subdirectory 添加子目录即可
• 包含源文件的子文件夹未包含 CMakeLists.txt 文件,子目录编译规则体现在主目录的 CMakeLists.txt 文件

2. 编译流程

在 Linux 平台下使用 CMake 构建 C/C++ 工程的流程如下:
• 编写 CMakeLists.txt 规则
• 执行 cmake $PATH 生成 Makefile(PATH 是CMakeLists.txt 所在的顶层目录)
• 执行 make 进行编译
注意一下 Linux 以下几个文件目录知识
• .或者 ./ 代表当前目录
• …或者 …/ 代表上一级目录
…/…或者 …/…/ 代表上上一级目录

3. CMake的两种构建方式

3.1. 内部构建 (in-source build) : 不推荐使用

内部构建会产生很多中间文件(Generated files,编译的中间文件和makefile文件),这些文件并不是我们最终想要的,和工程源代码文件放在一起会显得杂乱无章。
## 内部构建
# 在当前目录下,编译本目录的CMakeLists.txt,生成Makefile和其他文件
$ cmake .
# 执行make命令,生成target
$ make

3.2. 外部构建 (out-of-source build) : 推荐使用

将编译的目录和源代码目录区分开来,放在不同目录中
## 外部构建
# 1. 在当前目录下,创建build文件夹
$ mkdir build
# 2. 进入到build文件夹
$ cd build
# 3. 编译上级目录的CMakeLists.txt,生成Makefile和其他文件
$ cmake …
# 4. 执行make命令,生成target
$ make


## 编译工程 两种方式设置编译规则: 1. 包含源文件的子文件夹包含CMakeLists.txt文件,主目录的CMakeLists.txt通过add_subdirectory添加子目录即可 2. 包含源文件的子文件夹未包含CMakeLists.txt文件,子目录编译规则体现在主目录的CMakeLists.txt中
## 相关命令 • MESSAGE MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] “message to display” …) 向终端输出用户定义的信息或变量的值,SEND_ERROR:产生错误,生成过程被跳过;STATUS:输出前缀为—的信息;FATAL_ERROR:立即终止所有cmake过程

targets
Executable——add_executable、Libraries——add_library都可以算是target

最低版本要求
cmake_minimum_required (VERSION 2.8.7)

项目名称
project (projectname)
项目名称变量存储在PROJECT_NAME里。

该指定隐式引入了两个CMAKE的变量:
_BINARY_DIR,本例中是 projectname_BINARY_DIR(二进制文件保存路径)
_SOURCE_DIR,本例中是 projectname_SOURCE_DIR(源代码路径)

PROJECT_SOURCE_DIR
项目根目录,也就是CmakeLists.txt目录的绝对路径。

cmake变量
PROJECT_SOURCE_DIR:工程的根目录
PROJECT_BINARY_DIR:运行cmake命令的目录,通常为${PROJECT_SOURCE_DIR}/build
PROJECT_NAME:返回通过 project 命令定义的项目名称
CMAKE_CURRENT_SOURCE_DIR:当前处理的 CMakeLists.txt 所在的路径
CMAKE_CURRENT_BINARY_DIR:target 编译目录
CMAKE_CURRENT_LIST_DIR:CMakeLists.txt 的完整路径
EXECUTABLE_OUTPUT_PATH:可执行文件的存放位置
LIBRARY_OUTPUT_PATH:生成库的文件目录

find_package
项目通过该语句找到外部库、程序、文件等。
可以通过以下标准变量找到模块:
XXX_FOUND——如果没有找到则为false
XXX_INCLUDE_DIRS
XXX_LIBRARIES——要link的库,
XXX_DEFINITIONS
XXX_EXECUTABLE
XXX_LIBRARY DIRS

CMAKE_BUILD_TYPE
编译类型,默认为Debug
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_BUILD_TYPE Release)

set
SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])
定义变量(可以定义多个VALUE,如SET(SRC_LIST main.c util.c reactor.c))
set(KEY VALUE)接受两个参数,用来声明变量。在camke语法中使用KEY并不能直接取到VALUE,必须使用${KEY}这种写法来取到VALUE。

include_directories
指定’查找头文件’的搜索路径,它提供了一个’搜索头文件暂时的根目录’,相当于VS工程中设置“包含目录”,避免了在引用头文件时添加很长的路径。
include_directories(directories)
补充: 官网’不推荐’使用INCLUDE_DIRECTORIES

target_include_directories
target_include_directories( [SYSTEM] [AFTER|BEFORE]
<INTERFACE|PUBLIC|PRIVATE> [items1…]
[<INTERFACE|PUBLIC|PRIVATE> [items2…] …])
为指定目标(target)添加搜索路径,指定目标是指通过如add_executable(),add_library()这样的命令生成的。
INTERFACE、PUBLIC、PRIVATE会限制后面包含路径的作用范围,一般用PUBLIC即可;[items1…]即为头文件搜索路径。
target_include_directories 只会为指定目标包含头文件搜索路径。如果想为不同目标设置不同的搜索路径,那么用target_include_directories更合适。
include_directories和target_include_directories关系有点类似VS工程中的“包含目录”和“附加包含目录”区别,一个是全局,一个是针对单个工程而言。
举个栗子:
add_library(${PROJECT_NAME} SHARED Message.cpp)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)

搜集源文件——aux_source_directory
#包含原程序,即把给定目录下的源程序复制给变量DIR_SRC,但是这里一般都把生成的可执行文件放在bin目录中。
aux_source_directory(DIR_SRC ./)
aux_source_directory(src SRC_SUB)//src对应目录里搜索源文件,保存在文件列表SRC_SUB里
aux_source_directory(. SRC_CUR) //在当前目录进行同样操作
aux_source_directory(. SRC) // 定义SRC变量,其值为当前目录下所有的源代码文件

生成可执行程序——add_executable
语法:add_executable( [WIN32] [MACOSX_BUNDLE][EXCLUDE_FROM_ALL] source1 source2 … sourceN)
用于指定从一组源文件 source1 source2 … sourceN 编译出一个可执行文件且命名为 name。
add_executable(变量名 源文件名)
add_executable(helloworld ${DIR_SRC})
executable(nicp_cloud_visualization nicp_cloud_visualization.cpp)

强调: add_executable’不包括’头’(.h)'文件

添加运行库——add_library
生成/添加静态库或者动态库
语法: add_library( [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] source1 [source2 …])
指定生成的库文件名称,会自动加上前缀和后缀
STATIC 生成静态库
SHARED 生成动态链接库
MODULE 在使用dyld的系统有效,若不支持dyld,等同于SHARED;EXCLUDE_FROM_ALL 表示该库不会被默认构建。
例:add_library(${PROJECT_NAME} SHARED library.cpp library.h)
如果指定库类型,默认编译生成的是静态库。

说明1: 每个’add_library’只能生成一个库–>‘静态|动态’,默认是’静态’库
说明2: 一个’.h’头文件对应的’.c|.cpp’可能有多个,这个时候需要’aux_source_directory’的指令–>‘同上’
SET(LIBHELLO_SRC hello.c java.c) -->‘再多就要使用’ -->‘aux_source_directory’
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})

SET_TARGET_PROPERTIES
设置输出的名称,设置动态库的版本和API版本

添加静态/动态库——link_directories
库文件搜索路径,一般用在add_executable之前。假设我们程序用到了在/usr/lib下的一个静态库libmy.a,那就需要添加如下两个命令
#库所在位置
link_directories(/usr/lib)

设置要链接的库——target_link_libraries
#程序编译时候链接库,将’库’和’二进制可执行程序’进行’链接’
语法: target_link_libraries( [item1 [item2 […]]][[debug|optimized|general] ] …)
用于指定 target 链接的依赖项 item1 item2 …。
target_link_libraries(helloworld my)
表示helloworld要连接my,需要需要保证my必须在helloworld之前生成。

TARGET_LINK_LIBRARIES(target lib1 lib2 …)
为target添加需要链接的共享库

target_link_libraries:添加’链接库’;
target_link_libraries(demo Hello) 将’可执行文件’与’Hello连接’成’最终’文件demo
细节: 换句话说’add_executable(demo ${SRC_LIST})‘还不是最终的’demo’,没有经过’链接’的环节
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6IMHpAFa-1670820641307)(设置要链接的库.png)]

细节: ‘TARGET_LINK_LIBRARIES’要写在’ADD_EXECUTABLE’后面
target_link_libraries里库文件的顺序’符合gcc链接顺序’的规则,即’被依赖的库’放在’依赖它的库’的后面
1)cmake中链接库的顺序是’a依赖b’,那么b放在a的后面。
2)例如’二进制可执行程序test’依赖a库,b库, ‘a库又依赖b 库’, 那么’顺序如下’:
TARGET_LINK_LIBRARIES(test a;b)
备注: 空格或’;'都可以

属性PRIVATE、PUBLIC、INTERFACE使用主要看头文件、源文件是否包含第三方文件头

头文件(.h,.hpp文件)源文件(.cpp文件)属性
INTERFACE
PRIVATE
PUBLIC

link_directories
链接路径,指定动态链接库或静态链接库的搜索路径。也相当于环境变量中增加’LD_LIBRARY_PATH’的路径的作用。该指令的作用’主要’是指定’要链接的库文件(static|dynamic)‘的路径,相当于vs工程的“库目录”。
可以指定’多个路径’,以’空格’分开,
link_directories仅对’其后面’的targets起作用!!!
link_directories(“${PROJECT_SOURCE_DIR}/library”)

add_subdirectory
如果想添加一个子项目或者模块,可以用它进行构建的子目录。
向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制的存放位置
可以包含.h、.c和.cpp文件,这种方式可以直接添加头文件和源文件,不需要通过INCLUDE_DIRECTORIES指定头文件。
语法:add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
add_subdirectory(${OPEN_SOURCES_DIRECTORY}/cpp_redis)

文件操作

  • file APPEND命令
    file(APPEND … )
    用于向文件中追加内容,如果文件不存在,会创建该文件,如果该文件存在不会覆盖文件中的旧内容,将内容追加到文件末尾。
    set(TEST_CONTENT “\nI am coming”)
    file(APPEND ${PROJECT_SOURCE_DIR}/test.cpp ${TEST_CONTENT})

  • file GLOB命令
    file(GLOB [LIST_DIRECTORIES true[false] [RELATIVE ] [CONFIGURE_DEPENDS] [ …])
    主要用于匹配规则在指定的目录内匹配到所需要的文件,并将文件赋值给变量。
    file (GLOB Copy_Files “.qml" ".xml”)
    file (COPY ${Copy_Files} DESTINATION ${CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG})

  • file RENAME命令
    file(RENAME )
    将旧文件重新命名为新名称newname.
    file(RENAME test_2.cpp test.cpp)

  • file MAKE_DIRECTORY命令
    file(MAKE_DIRECTORY [ …])
    用来创建新目录

  • file COPY命令
    file(COPY … DESTINATION


    [FILE_PERMISSIONS …]
    [DIRECTORY_PERMISSIONS … ]
    [NO_SOURCE_PERMISSIONS] [USE_SOURCE_PERMISSIONS]
    [FILES_MATCHING]
    [ [PATTERN | REGEX ]
    [EXCLUDE] [PERMISSIONS … ] ]
    […])
    用于将文件copy到目标目录中

install 命令
将动态库、可执行程序安装到指定目录

检测环境

操作系统CMAKE_SYSTEM_NAME
if(CMAKE_SYSTEM_NAME STREQUAL “Linux”)
message(STATUS “Configuring on/for Linux”)
elseif(CMAKE_SYSTEM_NAME STREQUAL “Darwin”)
message(STATUS “Configuring on/for macOS”)
elseif(CMAKE_SYSTEM_NAME STREQUAL “Windows”)
message(STATUS “Configuring on/for Windows”)
elseif(CMAKE_SYSTEM_NAME STREQUAL “AIX”)
message(STATUS “Configuring on/for IBM AIX”)
else()
message(STATUS “Configuring on/for ${CMAKE_SYSTEM_NAME}”)
endif()

检测处理器体系结构——32位or64位
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
target_compile_definitions(arch-dependent PUBLIC “IS_64_BIT_ARCH”)
message(STATUS “Target is 64 bits”)
else()
target_compile_definitions(arch-dependent PUBLIC “IS_32_BIT_ARCH”)
message(STATUS “Target is 32 bits”)
endif()



文件输出目录设置
注意:设置的时候要放在add_executable、add_library前面
方法一(常用):
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

注:CMAKE_RUNTIME_OUTPUT_DIRECTORY是指定可执行文件的输出目录,CMAKE_LIBRARY_OUTPUT_DIRECTORY是指定动态库或者静态库的输出目录,CMAKE_ARCHIVE_OUTPUT_DIRECTORY用于设置 ARCHIVE 目标的输出路径。

方法二:
set_target_properties( targets…
PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY “${CMAKE_BINARY_DIR}/lib”
LIBRARY_OUTPUT_DIRECTORY “${CMAKE_BINARY_DIR}/lib”
RUNTIME_OUTPUT_DIRECTORY “${CMAKE_BINARY_DIR}/bin”
)

方法三:
# set output directories for all builds (Debug, Release, etc.)
foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} )
string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG )
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} KaTeX parse error: Expected group after '_' at position 65: …UTPUT_DIRECTORY_̲{OUTPUTCONFIG} ${CMAKE_SOURCE_DIR}/lib )
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_SOURCE_DIR}/bin )
endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES )

常用变量

变量含义
PROJECT_NAME工程名
CMAKE_CURRENT_LIST_DIR表示正在处理的CMakeLists.txt 文件的所在的目录的绝对路径(2.8.3 以及以后版本才支持)
CMAKE_ARCHIVE_OUTPUT_DIRECTORY静、动态库的lib文件存放位置,
CMAKE_LIBRARY_OUTPUT_DIRECTORY?
CMAKE_RUNTIME_OUTPUT_DIRECTORY设置可执行程序、动态库dll的存储目录
CMAKE_SOURCE_DIR程顶层目录所在路径
CMAKE_CURRENT_SOURCE_DIR当前CMakeLists.txt所在的路径,建议使用CURRENT_SOURCE,不建议使用SOURCE_DIR,因为如果主工程目录改变了,SOURCE_DIR也就会改变,很容易造成编译错误
CMAKE_BINARY_DIR工程编译时的路径
EXECUTABLE_OUTPUT_PATH可执行文件.exe的输出路径
LIBRARY_OUTPUT_PATH静、动态库lib、dll文件的输出路径

include_directories 和target_include_directories的区别
target_include_directories() 的功能完全可以使用 include_directories() 实现。但是我还是建议使用 target_include_directories()。
target_include_directories为指定目标(target)添加搜索路径,指定目标是指通过如add_executable(),add_library()这样的命令生成的。
target_include_directories 只会为指定目标包含头文件搜索路径。如果想为不同目标设置不同的搜索路径,那么用target_include_directories更合适。
include_directories(header-dir) 是一个全局包含,针对的是所有target(而target_include_directorie只针对一个target),会向下传递。什么意思呢?就是说如果某个目录的 CMakeLists.txt 中使用了该指令,其下所有的子目录默认也包含了header-dir 目录,会增加搜索时间。
当然了,在最终子目录的 CMakeLists.txt 文件中,使用 include_directories() 和 target_include_directories() 的效果是相同的。
每一个目录都是一个模块,目录内部应将对外和对内的头文件进行区分,由模块的调用者决定模块是否被传递(PRIVATE,INTERFACE,PUBLIC)。

么用target_include_directories更合适。
include_directories(header-dir) 是一个全局包含,针对的是所有target(而target_include_directorie只针对一个target),会向下传递。什么意思呢?就是说如果某个目录的 CMakeLists.txt 中使用了该指令,其下所有的子目录默认也包含了header-dir 目录,会增加搜索时间。
当然了,在最终子目录的 CMakeLists.txt 文件中,使用 include_directories() 和 target_include_directories() 的效果是相同的。
每一个目录都是一个模块,目录内部应将对外和对内的头文件进行区分,由模块的调用者决定模块是否被传递(PRIVATE,INTERFACE,PUBLIC)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/82464.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

生信工作流框架搭建 | 03-nextflow与AWS批量计算

目录生信工作流框架搭建 | 03-nextflow与AWS Batch前情提要批量计算基本概念批量计算服务&#xff08;Batch Computing Service&#xff09;是一种适用于大规模并行批处理作业的分布式云服务。术语表AWS 构建如果你使用除大陆外的区域如果你恰好在EU或者Ireland如果你使用大陆区…

人为什么会穷,人穷的原因是什么

大家好&#xff0c;我是蝶衣王的小编&#xff0c;今天分享一下人为什么会穷 你玩的有多脏&#xff0c;你就有多成功。这里指的脏&#xff01;​不是传统意义上的脏&#xff0c;而是你是不是那种死心眼。 ​ 小时候都背过三字经&#xff0c;说到人之初&#xff0c;性本善。但是…

spring源码-bean的后置处理器

BeanPostProcessor BeanPostProcessor也称为Bean后置处理器&#xff0c;它是Spring中定义的接口&#xff0c;在Spring容器的创建过程中&#xff08;具体为Bean初始化前后&#xff09;会回调BeanPostProcessor中定义的两个方法。 BeanPostProcessor的源码如下: public interf…

FFU安装条件及八大步骤详解

FFU安装条件及八大步骤(FFU过滤器) FFU安装的条件、环境及安装人员的服饰要求: 温 度&#xff1a; 5℃~45℃ 相对湿度&#xff1a;不大于85%(35℃) 大气压力&#xff1a;86Kpa~106Kpa zui大尘埃浓度&#xff1a;3500粒/升(尘埃粒径不大于0.5um) 电 源&#xff1a;220V 50…

详解 TS 中的子类型兼容性

简介 在写 TypeScript 代码时经常遇到类型检查不通过的问题&#xff0c;这些问题根据编译器给出的错误提示以及修改建议多数可以快速修复。本文讲解的内容是编译器进行类型检查时的兼容性相关检查规则&#xff0c;这些规则在 TypeScript 语言背后默默发挥作用。不了解这些规则…

艾美捷寡聚脱氧核苷酸CpG ODN:ODN 1668

艾美捷CpG ODN&#xff1a;ODN 1668&#xff1a;具有硫代磷酸酯骨架的CpG寡脱氧核苷酸&#xff08;B型&#xff09;。小鼠TLR9&#xff08;Toll样受体9&#xff09;的特异性配体。 艾美捷Enzo CpG ODN&#xff1a;ODN 1668详细信息&#xff1a; 序列&#xff1a;5-tccatgtgtcc…

Akka 学习(九)Akka Cluster

参考文章 Gitter Chat&#xff0c;Akka 在线交流平台Akka Forums&#xff0c;Akka 论坛Akka in GitHub&#xff0c;Akka 开源项目仓库Akka Official Website&#xff0c;Akka 官网Akka Java API&#xff0c;Akka 应用程序编程接口《Akka入门与实践》 [加]Jason Goodwin&#x…

AI创业时代!这9个方向有钱途;AIGC再添霸榜应用Lensa;美团SemEval2022冠军方法分享;医学图像处理工具箱… | ShowMeAI资讯日报

&#x1f440;日报合辑 | &#x1f3a1;AI应用与工具大全 | &#x1f514;公众号资料下载 | &#x1f369;韩信子 &#x1f4e2; 2023年9个有前途的 AI 创业方向 https://www.aiplusinfo.com/blog/9-promising-artificial-intelligence-startup-ideas-for-2023/ 2022年&#x…

央视广告怎么做,做好央视广告的关键点有哪些

企业品牌打算投放央视广告&#xff0c;首先想到的是如何做才更有效果&#xff0c;往往本身就比较困惑。公司应该投入多少资金&#xff1f;应选用何种广告投放方案&#xff1f;有时公司内部的观点也是不同的。尤其是面对广告公司提供的众多方案&#xff0c;让负责人看着都头疼&a…

Tos-GPR-AMC,117961-27-0,标记肽Tos-GPR-7-氨基-4-甲基香豆素

胰蛋白酶和凝血酶的荧光底物 Tos-GPR-AMC, fluorogenic substrate for trypsin and thrombin. Kinetic data for Thrombin: kcat 180, Km 310 uM. 编号: 190611中文名称: 标记肽Tos-GPR-7-氨基-4-甲基香豆素英文名: Tos-Gly-Pro-Arg-AMCCAS号: 117961-27-0单字母: Tos-GPR-AM…

代码随想录训练营第6天

专题&#xff1a;哈希表 题目&#xff1a;有效的字母异位词 给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的字母异位词。 例如 输入: s "anagram", t "nagaram" 输出: true 说明: 你可以假设字符串只包含小写字母。 题目理解&…

av_interleaved_write_frame():Broken pipe

使用FFmpeg命令rtsp推流到Docker中MediaServer服务器&#xff0c;15秒timeout一到就会打印错误信息&#xff0c;如下图&#xff1a; av_interleaved_write_frame():Broken pipe 命令中指定rtsp传输方式为tcp&#xff08;-rtsp_transport tcp &#xff09;&#xff0c;虽然不会…

第二证券|锂电起火风险完美解决?美科学家研发新型超高盐度电解质

现在&#xff0c;研讨人员正致力于以各种方式改善电池技能&#xff0c;其中最重要的是处理可燃性问题。 美国科学家们近期研宣布了一种新的电解质配方&#xff0c;就能够以一种十分有出路的方式处理这一问题&#xff0c;依托额定的盐含量来防止有问题发生的化学反应。 众所周知…

[附源码]JAVA毕业设计疫情期间高校师生外出请假管理系统录屏(系统+LW)

[附源码]JAVA毕业设计疫情期间高校师生外出请假管理系统录屏&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&am…

婚礼策划预约小程序开发,拓展客户人群

婚礼对于所有人来说都是非常重要的一件事&#xff0c;是人生中最值得回忆的美好场景。在经济水平的不断提高下&#xff0c;人们在结婚之前都要找专业团队对婚礼进行策划&#xff0c;让婚礼更加完美&#xff0c;正因如此&#xff0c;婚礼策划行业得到了迅速发展。但是从众多策划…

Zabbix-proxy安装(zabbix 6.0LTS)

关于zabbix 系列的博文我已经很久没有更新了&#xff0c;主要原因是最近太忙了。如果读者诸君有认真阅读我前面的文章并亲自实践过的话&#xff0c;相信你肯定会大有收获的。到目前为止zabbix 的基础知识在我的博文中基本已经全都涉及到了&#xff0c;至于如何运用&#xff0c;…

赛狐ERP11月新功能汇总 | 13大场景,超90项功能升级

赛狐ERP月度《产品升级》栏目来啦&#xff01; 11月我们加紧迭代了运营、进销存、财务、报表等多个维度的功能内容&#xff0c;聚焦卖家关注的需求要点&#xff0c;进行了13大业务场景&#xff0c;超90项功能升级。赛狐ERP将不断优化产品细节&#xff0c;提升卖家体验&#xf…

CH36X系列接口芯片Linux系统开发库说明

一、概述 ch36x_lib库是Linux系统下用于开发CH36X系列设备CH365/CH367/CH368等芯片应用的软件接口库&#xff0c;此接口库主要提供以下功能&#xff1a; 设备打开/关闭 获取芯片类型/驱动版本 获取IO基地址/Memory基地址/中断号 配置空间读写&#xff08;支持单字节/双字节…

基于java+springboot+mybatis+vue+mysql的体育场馆运营系统

项目介绍 在系统流程分析当中调查分析它是比较重要的环节&#xff0c;因为在这个系统当中它都涉及到每个环节的业务流程&#xff0c;所以从计算机毕业设计SpringBootVue选题推荐—体育场馆运营系统的设计的整体设计上要保证各个信息的正确输入和输出以及对数据储存的完整&…

linux下JDK安装

先下载离线安装包&#xff0c;我将安装包直接放到/root/softPackages目录下&#xff08;需要安装包可私聊&#xff09; 1.卸载已有OpenJDK(如果有) 查找已经安装的OpenJDK包 rpm -qa | grep java 如果有查出结果&#xff0c;直接yum -y remove卸载即可&#xff1a; 例如&a…