C++编译之(3)-camke/CMakeLists.txt的编译使用教程

news2024/11/26 14:35:28

引言

上一节介绍了前面我们介绍了make/Makefile来对c++项目进行编译,我们继续以该项目为例讲解;

C++编译之(1)-g++单/多文件/库的编译
C++编译之(2)-make及makefile编译过程

我们先看看上一节的实战的目录结构如下:

- mutilFilesDemo
  - include // 头文件目录
    - HelloTools.h
    - Prints.h
  - libs // 库子项目目录
    - ToolLibs.h
    - ToolLibs.cpp
    - Makefile  // 子项目Makefile
  - src // 源码目录
    - module // 源码模块
      - Prints.cpp // Prints类
    - HelloTools.cpp // HelloTools类
  - main.cpp // main类
  - Makefile  // 主项目Makefile

make与Makefile,cmake与CMakeLists.txt

make用来编译c++项目,make命令根据Makefile中配置的编译链接关系;由于Makefile文件的制作是个大工程,因此出现了cmake工具cmake根据CMakeLists.txt来执行cmake命令;

使用CMake编写跨平台工程的流程如下:

(1)编写源文件

(2)编写CMakeLists.txt

(3)由CMake根据CMakeLists.txt来生成相应的makefile文件

(4)使用make并根据makefile调用gcc来生成相应的可执行文件

CMake是一个可以跨平台的编译工具,可以用简单的语句来描述所有平台的编译过程。他能够输出各种各样的 makefile 或者工程文件。和make与makefile类似,我们在使用CMake时同样也需要一个文件来提供规则,这个文件就是CMakeLists

CMakeLists.txt

编写CMakeLists.txt最常用的功能就是调用其他的.h头文件和.so/.a库文件,将.cpp/.c/.cc文件编译成可执行文件或者新的库文件。

# 指定cmake最小版本
cmake_minimum_required(VERSION 3.4.1)

# 本CMakeLists.txt的project名称
# 会自动创建两个变量,PROJECT_SOURCE_DIR和PROJECT_NAME 
# ${PROJECT_SOURCE_DIR}:本CMakeLists.txt所在的文件夹路径
# ${PROJECT_NAME}:本CMakeLists.txt的project名称
# CMAKE_BINART_DIR, PROJECT_BINARY_DIR, <projectName>_BINARY_DIR:这三个变量的含义一样。
project(xxx)

# 获取路径下所有的.cpp/.c/.cc文件,并赋值给变量中
aux_source_directory(路径 变量)

# 给文件名/路径名或其他字符串起别名,用${变量}获取变量内容
set(变量 文件名/路径/...)

# 添加编译选项
add_definitions(编译选项)

# 打印消息
message(消息)

# 编译子文件夹的CMakeLists.txt
add_subdirectory(./subProject) 

# 将.cpp/.c/.cc文件生成可执行文件
add_executable(main main.cpp)

# 将.cpp/.c/.cc文件生成.a静态库 // add_library(库文件名称 STATIC 文件)
# 注意,库文件名称通常为libxxx.so,在这里只要写xxx即可
# 生成静态库(默认) 
add_library(util STATIC util.cpp)
# 生成动态库
add_library(util SHARED util.cpp)

# 规定.h头文件路径
include_directories(路径)

# 规定.so/.a库文件路径
link_directories(路径)

# 对add_library或add_executable生成的文件进行链接操作
# 注意,库文件名称通常为libxxx.so,在这里只要写xxx即可
target_link_libraries(可执行文件名称 链接的库文件名称)
# 如果是链接的动态库,则运行的时候需要把它拷贝到可执行文件名称同目录下

如何设置DGB调试模式请看这里

CMakeLists的编写过程的方法

1. 指定 cmake 的最小版本

cmake_minimum_required(VERSION 3.4.1)

2.设置项目名

project(myProject)

它会引入两个变量 myProject_BINARY_DIR 和 myProject_SOURCE_DIR,同时,cmake 自动定义了两个等价的变量 PROJECT_BINARY_DIR 和 PROJECT_SOURCE_DIR

3.设置编译类型

// 将.cpp/.c/.cc文件生成可执行文件
add_executable(main main.cpp)
// 生成静态库(默认) 
add_library(util STATIC util.cpp tools.cpp)
// 生成动态库
add_library(util SHARED util.cpp tools.cpp)

不加STATIC|SHARED 默认为生成静态库;此外,生成的库,默认会加前缀lib,及后缀*.a|*.so

4.搜索所有cpp文件

aux_source_directory(. SRC_LIST)
add_library(demo ${SRC_LIST})

发现一个目录下所有的源代码文件,并将列表存储再一个变量中(不会递归遍历目录)

5.自定义搜索规则

file(GLOB SRC_LIST "*.cpp" "protocol/*.cpp")
add_library(demo ${SRC_LIST})
#或者
file(GLOB SRC_LIST "*.cpp")
file(GLOB SRC_PROTOCOL_LIST "protocol/*.cpp")
add_library(demo ${SRC_LIST} ${SRC_PROTOCOL_LIST})
#或者
aux_source_directory(. SRC_LIST)
aux_source_directory(protocol SRC_PROTOCOL_LIST)
add_library(demo ${SRC_LIST) ${SRC_PROTOCOL_LIST)

6.指定查找的库文件

find_library( # Sets the name of the path variable.
              log-lib
 
              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

查找到指定的预编译库,并将它的路径存储在变量中。默认的搜索路径为 cmake 包含的系统库。

类似的命令还有 find_file()、find_path()、find_program()、find_package()。

7.设置包含的目录

include_directories(
    ${CMAKE_CURRENT_SOURCE_DIR}
    ${CMAKE_CURRENT_BINARY_DIR}
    ${CMAKE_CURRENT_SOURCE_DIR}/include
)

Linux 下还可以通过如下方式设置包含的目录

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I${CMAKE_CURRENT_SOURCE_DIR}")

8.设置链接库搜索目录

link_directories(
    ${CMAKE_CURRENT_SOURCE_DIR}/libs
)

Linux 下还可以通过如下方式设置包含的目录

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_CURRENT_SOURCE_DIR}/libs")

9.设置target需要链接的库

target_link_libraries( # 目标库
                       demo
 
                       # 目标库需要链接的库
                       # log-lib 是上面 find_library 指定的变量名
                       ${log-lib} )
target_link_libraries(demo libface.a) # 链接libface.a
target_link_libraries(demo libface.so) # 链接libface.so

注意,库文件名称通常为libxxx.so,在这里只要写xxx即可,如需要明确指定可加上前后缀

10.使用变量

# set 直接设置变量的值
set(SRC_LIST main.cpp test.cpp)
add_executable(demo ${SRC_LIST})

# set 追加设置变量的值
set(SRC_LIST main.cpp)
set(SRC_LIST ${SRC_LIST} test.cpp)
add_executable(demo ${SRC_LIST})

# list 追加或者删除变量的值
set(SRC_LIST main.cpp)
list(APPEND SRC_LIST test.cpp)
list(REMOVE_ITEM SRC_LIST main.cpp)
add_executable(demo ${SRC_LIST})

11.添加编译选项

功能1

add_definitions的功能和C/C++中的#define是一样的

# 添加一个宏定义,设置后,代码中即可使用 `TEST_DEBUG`这个宏,等同在代码中增加 #define TEST_DEBUG
add_definitions(-DTEST_DEBUG)

于是cpp代码中,就可以使用TEST_DEBUG这个宏了

#ifdef TEST_DEBUG
...
#else 
...
#endif

问题是,由谁来驱动定义这个宏呢?通过结合options指令可以实现

# 设置一个宏选项默认值ON,
# option选项 不会影响到cpp代码(不会添加#define宏)
option(TEST_DEBUG "test"  ON)
if(TEST_DEBUG )
	message("itis" ${TEST_IT_CMAKE})
	add_definitions(-DTEST_DEBUG )
endif()

最后,在执行cmake时,就可以设置该选项了,并传递该值下去;

cmake .. -DTEST_DEBUG=1

通过cmake-gui也可以很方便的配置选项,如下:
在这里插入图片描述

功能2
add_definitions("-Wall -g")
#没加之前
gcc -c main.c -o test
#添加之后,相当于
gcc -g -Wall -c main.c -o tes

12.复杂项目,子项目

# 添加subProjectDir子目录
add_subdirectory(subProjectDir)

subProjectDir目录的CMakeLists.txt可以这样写:

aux_source_directory(. DIR_LIB_SRCS)
# 生成链接库
add_library(subFuns ${DIR_LIB_SRCS})

13.其他

  1. 常用的预定义变量
变量说明
PROJECT_SOURCE_DIR工程根目录
PROJECT_BINARY_DIR运行cmake命令的目录,通常是${PROJECT_SOURCE_DIR}/build
PROJECT_NAME返回通过project命令定义的项目名称
CMAKE_CURRENT_SOURCE_DIR当前处理的CMakeLists.txt所在的路径
CMAKE_CURRENT_BINARY_DIRtarget 编译目录
CMAKE_CURRENT_LIST_DIRCMakeLists.txt的完整路径
CMAKE_CURRENT_LIST_LINE当前所在的行
CMAKE_MODULE_PATH定义自己cmake模块所在的路径。SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake),然后可以用INCLUDE命令来调用自己的模块
EXECUTABLE_OUTPUT_PATH重新定义目标二进制可执行文件的存放位置
LIBRARY_OUTPUT_PATH重新定义目标链接库的存放位置
  1. 环境变量

    1. 使用环境变量$ENV{name}
    2. 写入环境变量 set(ENV{name} value)
  2. cmake命令的常用参数

Cmake命令行使用:
-G 指明生成的Makefile格式
-D 添加参数
-S 指明源码位置
-B 指明输出路径
例如:
cmake -G “MinGW Makefiles” -S “源码路径” -B “输出路径”
或者
cmake -G “MinGW Makefiles” -D CMAKE_TOOLCHAIN_FILE=“编译工具链路径” -S “源码路径” -B “输出路径”
注意:Cmake是不支持中文的,无论是GUI还是命令行,都严禁出现中文字符.
  1. Do’s and Don’ts
    不好的 CMake 的用法
        不要使用全局函数,例如 link_directories,include_libraries,add_definitions 等,请你忘记它们
        不要滥用 PUBLIC,除非有依赖传递,否则请你使用 PRIVATE 替换 PUBLIC
        不要使用 GLOB 来添加文件
        不要直接链接文件,而是链接目标
        链接时千万不要跳过 PUBLIC/PRIVATE,这会导致未来的链接都没有关键字

    良好的 CMake 用法
        把 CMake 视作代码,保持它的整洁和可读性
        围绕 target 构建你的 CMake。将需要的信息打包在 target 里,然后链接那个目标
        导出你的接口
        写 Config.cmake 文件,这是一个库作者应该做的,可以方便别人使用你的库
        使用 ALAS 目标,以保持使用一致性
        将常用的功能提取成函数或者宏,通常函数更好
        使用小写的函数名,全大写是变量
        使用 cmake_policy 或者 range of versions

如何使用CMakeLists.txt 完成一次编译过程

我们以上一节的项目为例,改造成CMakeLists.txt实现编译。我们首先删除两个Makefile文件,并创建两个CMakeLists.txt,同样是多文件夹、多项目的多层次编译案例,如下所示(其他文件不用改)

- mutilFilesDemo
  - include // 头文件目录
    - HelloTools.h
    - Prints.h
  - libs // 库子项目目录
    - ToolLibs.h
    - ToolLibs.cpp
    - CMakeLists.txt  // 子项目CMakeLists.txt
  - src // 源码目录
    - module // 源码模块
      - Prints.cpp // Prints类
    - HelloTools.cpp // HelloTools类
  - main.cpp // main类
  - CMakeLists.txt  // 主项目CMakeLists

如未看过前面的教程,请点这里看上一节

1、我们首先给出子项目libsCMakeLists.txt的源码

CMakeLists.txt

cmake_minimum_required(VERSION 3.4.1)
project(subLibPro)
aux_source_directory(. SRC_LIST)
add_library(ToolLibs STATIC ${SRC_LIST})

我们进入libs目录,首先创建一个build临时的编译目录,再执行一下cmake

$ cd mutilFilesDemo/libs
$ mkdir build
$ cd build
$ cmake ..
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/mutilFilesDemo/libs/build

执行成功后,在build目录下自动创建了Makefile,有了这个文件,我们可以直接执行make进行编译

# 先看看cmake后,创建了写啥东西
$ ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  Makefile
# 在执行一下make
$ make
Scanning dependencies of target ToolLibs
[ 50%] Building CXX object CMakeFiles/ToolLibs.dir/ToolLibs.cpp.o
[100%] Linking CXX static library libToolLibs.a
[100%] Built target ToolLibs
# 编译成功后,最后再查看一下目录是否生成我们需要的静态库
$ ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  libToolLibs.a  Makefile

我们看到,成功生成了我们需要的libToolLibs.a

2、接着我们看看如何创建主项目的CMakeLists.txt

直接先贴出代码

cmake_minimum_required(VERSION 3.4.1)

# 项目名称
project(mainPro)

# 设置子项目目录变量-libs
set(SUB_PROJ_LIBS_DIR libs)

# 设置主项目依赖的库名变量-libToolLibs.a
set(MAIN_LIBS ToolLibs)

# 添加子项目
add_subdirectory(${SUB_PROJ_LIBS_DIR})

# 搜索主项目源码
file(GLOB SRC_LIST "*.cpp" "src/*.cpp" "src/modules/*.cpp")

# 生成可执行目标
add_executable(${PROJECT_NAME} ${SRC_LIST})

# 添加库目录
link_directories(${PROJECT_NAME} ${SUB_PROJ_LIBS_DIR})

# 添加链接库
target_link_libraries(${PROJECT_NAME} ${MAIN_LIBS})

我们在mutilFilesDemo目录下创建一个build目录,用于生成编译文件;同时删除前面子项目编译过程中,创建的build目录

$ cd mutilFilesDemo
$ mkdir build
$ cd mutilFilesDemo/libs
$ rm -rf ./build
$ cd mutilFilesDemo/build
$ cmake ..
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/mutilFilesDemo/build

成功创建Makefile,继续执行make

$ make
Scanning dependencies of target ToolLibs
[ 16%] Building CXX object libs/CMakeFiles/ToolLibs.dir/ToolLibs.cpp.o
[ 33%] Linking CXX static library libToolLibs.a
[ 33%] Built target ToolLibs
Scanning dependencies of target mainPro
[ 50%] Building CXX object CMakeFiles/mainPro.dir/main.cpp.o
[ 66%] Building CXX object CMakeFiles/mainPro.dir/src/HelloTools.cpp.o
[ 83%] Building CXX object CMakeFiles/mainPro.dir/src/modules/Prints.cpp.o
[100%] Linking CXX executable mainPro
[100%] Built target mainPro

非常完美,一点不拖泥带水;子库项目的CMakeLists.txt自动执行,而且自动帮你把项目编译的过程文件全部统一放在了最外层的build目录下,就像我们上一节直接用Makefile编写的一样;而且静态库自动链接上,只需要指定静态库的大致目录即可(甚至不需要指定link_directories,cmake会自动帮你在整个编译的工作目录下即build自动搜素需要的库)

们尝试执行一下mainPro

$ ./mainPro
Hello world!
MAX_NUM+n:110
=================================
使用静态库-add(a,b)
结果为:a+b=500

跟上一节的结果一模一样

参考文献
C++编译之(1)-g++单/多文件/库的编译
C++编译之(2)-make及makefile编译过程
CMakeLists的基本使用方法
https://zhuanlan.zhihu.com/p/473573789

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

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

相关文章

Docker入门与应用

Docker入门与应用1.初识Docker1.1.什么是Docker1.1.1.应用部署的环境问题1.1.2.Docker解决依赖兼容问题1.1.3.Docker解决操作系统环境差异1.1.4.小结1.2.Docker和虚拟机的区别1.3.Docker架构1.3.1.镜像和容器1.3.2.DockerHub1.3.3.Docker架构1.3.4.小结1.4.安装Docker2.Docker的…

“华为杯”研究生数学建模竞赛2005年-【华为杯】D题:仓库容量有限条件下的随机存贮管理(附获奖论文)

赛题描述 工厂生产需定期地定购各种原料,商家销售要成批地购进各种商品。无论是原料或商品,都有一个怎样存贮的问题。存得少了无法满足需求,影响利润;存得太多,存贮费用就高。因此说存贮管理是降低成本、提高经济效益的有效途径和方法。 问题2 以下是来自某个大型超市的…

全链路追踪 jaeger

Jaeger 概述 Jaeger 是 Uber 开发并开源的一款分布式追踪系统&#xff0c;兼容 OpenTracing API&#xff0c;适用于以下下场景&#xff1a; 分布式跟踪信息传递分布式事务监控问题分析服务依赖性分析性能优化 特性 高扩展性 Jaeger后端的设计没有单点故障&#xff0c;可以…

大数据 | 《Riffle:Optimized Shuffle Service for Large-Scale》论文阅读

1. 简介 1.1. 近期工作 研究工作鼓励运行大量小任务 小任务能提高并行性&#xff0c;减少端到端耗时工程经验反对运行过多的任务 过多的task在shuffle阶段会引入大量IO开销&#xff0c;根本原因在于map和reduce阶段之间的shuffle IO请求数量随着任务数量的增长呈现指数级的增…

emoji 符号大全,给各位程序员增加一些奇怪的知识点

这篇博客非常有意思&#xff0c;我将为大家整理和罗列一些好用的 emoji 表情站点。 文章目录EmojiXDcarpedm20emoji-cheat-sheetemojiterrafsymbols符号大全unicode.orgemojiallemojiguideemojipediaemoji696 编辑器emoji.inkEmoji Artemojifinderemoji 可以在许多社交媒体平台…

Redis 持久化-AOF

Redis 持久化-AOF 1.官方资料 在线文档 : https://redis.io/topics/persistence 2.AOF 是什么? 1、AOF(Append Only File) 2、以日志的形式来记录每个写操作(增量保存)&#xff0c;将 Redis 执行过的所有写指令记录下来(比 如 set/del 操作会记录, 读操作 get 不记录) 3、…

【大数据趋势】1月24日 美元关键位置上,应该不会一次破,纳指有概率反弹,人民币结汇行情结束在即。

确定市场形态 - 美元指数 关键位置大概率不会一次就破&#xff0c;有较强反弹 作为长期的关键位置101-103这个区域&#xff0c;没有可能一次性涨破&#xff0c;或者一次性跌破&#xff0c;所以大概率有一次反弹出现。作为趋势线&#xff08;红色&#xff09;来看&#xff0c…

十大经典排序算法(动态演示+代码)-冒泡算法

时间、空间复杂度比较 排序算法平均时间复杂度最差时间复杂度空间复杂度数据对象稳定性冒泡排序O(n2)O(n2)O(1)稳定选择排序O(n2)O(n2)O(1)数组不稳定、链表稳定插入排序O(n2)O(n2)O(1)稳定快速排序O(n*log2n)O(n2)O(log2n)不稳定堆排序O(n*log2n)O(n*log2n)O(1)不稳定归并排序…

万能四码(0126版本)之分析

万能四码&#xff08;0126版本&#xff09;之分析一、万能四码的重新排列原版是这样的&#xff1a;0126&#xff0c;0134&#xff0c;0159&#xff0c;0178&#xff0c;0239&#xff0c;0247&#xff0c;0258&#xff0c;0357&#xff0c;0368&#xff0c;0456&#xff0c;0489…

【进阶C语言】程序环境与预处理

文章目录一.程序环境1.翻译环境编译器1.预处理2.编译3.汇编链接器2.运行环境总图解二.预处理1.预定义符号2.define1.define的定义2.替换规则3.定义的建议和使用的缺点1.加括号2.避免使用带有副作用的符号3.命名约定4.#和##1.#2.##5.宏和函数的对比6.undef3.条件编译1.常量表达式…

趣味三角——第3章——6个三角函数的成熟过程

目录 3.1 6个三角函数的演化进程简述 3.2 Johann Muller(别名Regiomontanus)的贡献 第3章 6个三角函数的成熟过程 It is quite difficult to describe with certainty the beginning of trigonometry . . . . In general, one may say that the emphasis was placed first …

ThinkPHP5 Request类method任意方法调用RCE

ThinkPHP v5.0.x 影响版本&#xff1a;5.0.0 < version < 5.0.23 漏洞点&#xff1a;\think\Request::method 修复&#xff1a;版本更新 top-think/framework4a4b5e6 改进Request类 环境 thinkphp5.0.23核心版&#xff08;需开启debug&#xff09;thinkphp5.0.22完…

设计模式 - 六大设计原则之LoD(迪米特法则原则)

文章目录概述Case学生类老师类Bad ImplBetter Impl老师类改造调用方&#xff1a;校长类改造概述 迪米特法&#xff08;Law Of Demeter &#xff0c; LoD&#xff09;则又叫最少知道原则&#xff08;Least Knowledge Principle&#xff09;&#xff0c;最早是在1987年由美国Nor…

【游戏客户端】如何实现环形进度条

【游戏客户端】如何实现环形进度条 Hello大家好&#xff0c;我是Lampard。好久没写博客了&#xff0c;之前在忙着制作项目的一个大的副本&#xff0c;趁着过年得闲&#xff0c;和大家分享一下制作过程中遇到的一些有趣的问题。今天主要是分享如何在cocos制作一个环形的进度条 (…

重写 equals 时为什么一定要重写 hashCode

equals 方法和 hashCode 方法是 Object 类中的两个基础方法&#xff0c;它们共同协作来判断两个对象是否相等。为什么要这样设计嘞&#xff1f;原因就出在“性能” 2 字上。 使用过 HashMap 我们就知道&#xff0c;通过 hash 计算之后&#xff0c;我们就可以直接定位出某个值存…

移动web 空间转换 3D

移动web 空间转换 3D空间转换 3D3D位移透视3D旋rotateXrotateY左手法则立体呈现空间转换 3D 3D坐标系 3D 坐标系比2D 多了一个Z轴。 一定要记住3个坐标轴取值的正反&#xff1a; X 轴 往右越大&#xff0c;是正值&#xff0c; 否则反之Y 轴 往下越大&#xff0c;是正值&…

React错误边界

首先 我们先构建出问题的场景 我们创建一个react项目 然后在src下创建 components 文件夹目录 在下面创建一个 error.jsx 组件 参开代码如下 import React from "react";export default class App extends React.Component{constructor(props){super(props);this.…

CUDA编程笔记(5)

文章目录前言CUDA的内存组织全局内存常量内存纹理内存和表面内存寄存器局部内存共享内存L1和L2缓存SM的构成API函数查询设备总结前言 cuda的内存组织&#xff0c;在使用GPU时尽可能提高性能&#xff0c;合理的使用设备的内存也是十分重要的。 CUDA的内存组织 如表所示&#…

Docker基本操作

Docker基本操作一、镜像操作1.镜像名称2.镜像命令&#xff08;1&#xff09;拉取、查看镜像&#xff08;2&#xff09;保存、导入镜像二、容器操作1.容器相关命令2.创建并运行一个容器3.进入容器&#xff0c;修改文件4.小结三、数据卷&#xff08;容器数据管理&#xff09;1.什…

Java:枚举类型

Java&#xff1a;枚举类型 每博一文案 师父说&#xff1a;人活一世&#xff0c;每个人都有他的特别&#xff0c;每个人都值得被温柔相待。红尘一遭&#xff0c;每段经历都有它的必然&#xff0c; 每段经历都造就了现在的你&#xff0c;最快乐的事情&#xff0c;就是做自己&…