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

现代 cmake (cmake 3.x) 操作大全

  cmake 是一个跨平台编译工具,它面向各种平台提供适配的编译系统配置文件,进而调用这些编译系统完成编译工作。cmake 进入3.x 版本,指令大量更新,一些老的指令开始被新的指令集替代,并加入了一些更加高效的指令/参数。本文归纳了cmake 3.x 版本的常用指令,方便使用时备查。

  关于cmake工具的简单介绍和VS Code cmake Tools 环境配置,可以参考我的另一篇博客。本文参考资料:【公开课】现代CMake高级教程 - Bilibili 小彭老师,CMake Reference Documentation

ps: 本文是大全类文档,适合备查,完整学习cmake强烈建议跟随官方tutorial,会有非常好的效果

cmake 项目构建流程

典型的cmake 项目构建流程如下:

  1. 配置阶段 Configure:根据编写的CmakeLists.txt文件,以及选择的编译系统,生成该系统的构建规则文件。(例如,对make生成Makefile,对MSVC生成sln(可以在VS中打开))

    cmake -B build
    
    • 以上指令可以在当前目录下创建build目录,而不需要事先创建并进入
    • 通过-D设置缓存变量,格式-D<OPTION>=<VALUE>,如:
      • 编译器路径:CMAKE_C_COMPILTER, CMAKE_CXX_COMPILER
      • 安装路径(在Configure阶段配置):CMAKE_INSTALL_PREFIX
      • 构建模式:CMAKE_BUILD_TYPE
      • 自定义缓存变量:-Dvar:type=value,可以将option设定为OFF,即表示不启用(会覆盖CMakeLists中的默认选项)
    • -G指定生成器(Generator,即构建系统),可以通过--help查看支持的列表
      • -A 指定架构(For MSVC build system)
      • -T 指定工具链,例如使用ClangCL: -T ClangCL,host=x64 (For MSVC build system)
      • 推荐使用Ninja作为生成器,效率较高
  2. 编译阶段 Build:根据生成的构建规则,调用构建系统进行构建,这一步真正输出项目目标(可执行文件、共享库等)

    cmake --build build
    
  3. 构建完成后,可以在build目录下找到输出结果(MSVC并不是直接放在build下,而是在构建模式对应目录下(Debug, Release),这与其他不同)

项目配置变量

项目配置变量是控制项目构建,以及包含项目信息的关键变量。这些变量可以在命令行配置(缓存变量),也可以在CMakeLists内部修改。

项目构建模式

一般有四种项目构建模式:

  • Debug 调试模式:不优化,生成调试信息 -O0 -g
  • Release 发布模式:最优化,性能最佳 -O3 -DNDEBUG
  • MinSizeRel 最小体积发布 :生成项目文件小,性能优化不完全 -Os -DNDEBUG
  • RelWithDebInfo 带调试信息发布 -O2 -g -DNDEBUG
  • 默认为Debug模式

可以通过在CMakeLists中增加默认选项脚本的方法修改默认选项为Release

if (NOT CMAKE_BUILD_TYPE)set(CMAKE_BUILD_TYPE Release)
endif()

项目信息

使用命令project初始化项目信息

project(<PROJECT-NAME> [<language-name>...])
project(<PROJECT-NAME>[VERSION <major>[.<minor>[.<patch>[.<tweak>]]]][DESCRIPTION <project-description-string>][HOMEPAGE_URL <url-string>][LANGUAGES <language-name>...])
  • language: 指定项目使用语言,默认C CXX
    • 支持C CXX ASM FORTRAN CUDA OBJC OBJCXX ISPC
  • VERSION 字段:设置项目版本号,会自动配置相关变量

该命令将初始化名为project_name的项目,并给相关变量赋值:

  • PROJECT_NAME: 项目名称
  • CMAKE_PROJECT_NAME:根项目名称
  • PROJECT_SOURCE_DIR:项目源码路径,即初始化project的CMakeLists.txt所在路径
  • PROJECT_BINARY_DIR:项目输出路径,通常是./build路径
  • CMAKE_CURRENT_SOURCE_DIR:当前源码路径
  • CMAKE_CURRENT_BINARY_DIR:当前输出路径,即当前CMakeLists.txt所在路径,子模块中指子模块路径
  • 更多属性,请参考project — CMake 3.25.1 Documentation

项目语言标准

一般通过如下指令设置标准(推荐放在project指令前,会在project语言启用时检测)

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)
  • 设置C标准为C11, C++设置CXX对应属性
  • CMAKE_C_STANDARD_REQUIRED 在启用语言时检查编译器是否支持该标准
  • CMAKE_C_EXTENSIONS 是否启用GNU拓展语言特性(对跨平台有影响)

添加构建目标

构建目标主要有两种类型:

可执行文件 executable

使用add_executable命令添加可执行文件目标:

add_executable(<name> [WIN32] [MACOSX_BUNDLE][EXCLUDE_FROM_ALL][source1] [source2 ...])
  • 添加一个name的可执行文件目标,源文件来自source
    • 可以是列表或者空格分开的多个文件名
    • 也可以是变量${var_name},目录的所有文件可以使用 aux_source_directory添加
  • 其中,source可以省略(>3.11),并在后面以target_sources的形式给出

库 library

add_library(<name> [STATIC | SHARED | MODULE][EXCLUDE_FROM_ALL][<source>...])
  • STATIC/SHARED 指定生成静态库/动态库,默认静态

另外还有对象库object library

add_library(<name> OBJECT [<source>...])
  • 对象库不输出实际的库文件,而是可以直接被加入到其他构建目标中,如:

    add_library(... $<TARGET_OBJECTS:objlib> ...)
    add_executable(... $<TARGET_OBJECTS:objlib> ...)
    

    或者使用target_link_libraries()链接到对象库(CMAKE >3.12)

  • 注意:动态库不能直接引用静态库,因为动态库开启PIC,而静态库没有

    • 解决方案:使用对象库替代静态库,或者为静态库配置PIC
      set_property(TARGET target_name PROPERTY POSITION_INDEPENDENT_CODE ON)
      
  • 另外,Windows平台如果要使用动态库,则需要添加宏

    • 声明前添加

      #ifdef _MSC_VER__declspce(dllimport)
      #endif
      
    • 定义前加

      #ifdef _MSC_VER__declspce(dllexport)
      #endif
      

配置构建目标

设置对象属性

set_target_properties(target_name PROPERTIESproperty_name value...)

使用set_target_properties设置编译目标属性

这些属性包括(详细信息参考cmake-properties(7) — CMake 3.25.1 Documentation):

  • 语言标准版本
  • 编译器设置
  • 目标输出位置*_OUTPUT_DIRECTORY

链接三方库

使用target_link_libraries()链接第三方库

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

其中,item可以是:

  • 库对象名(使用add_library( IMPORTED)引入)
  • 指向库文件的完整路径
  • 库文件名,这会调用链接器自动搜索(在Linux下可以依据lib搜索)

优化方案(对使用cmake的三方库,限Linux):

find_package(LIBRARY_NAME REQUIRED)
target_link_libraries(<target> [PUBLIC] LIBRARY_NAME::library_target_name)
  • 使用find_package会在/usr/lib/cmake下增加.cmake配置文件,cmake会自动搜索并链接相应的库。
  • 另外,在链接库的时候,还会按照配置文件进行引用传播,引用其的对象自动引用其头文件目录。

编译时定义

使用target_compile_definitions来配置编译时宏定义,这些定义可以在C/C++的宏中被使用

target_compile_definitions(target PUBLIC def)
  • 将def设置到target的编译过程中

安装 install

install(TARGETS <target>... [destination])

以上命令用于安装对象到destination

子命令还可以是:

  • FILES 安装文件,如头文件等
  • DIRECTORY 目录
  • 详见install — CMake 3.25.1 Documentation

部署 ctest

使用enable_testing以启用ctest,ctest会自动执行命令,并匹配输出,自动化完成测试

以下示例增加一个ctest,并设置匹配的输出结果

add_test(NAME Usage COMMAND Tutorial)
set_tests_properties(UsagePROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number")

如果程序输出:Usage:[any]number,就算正确通过

还可以将测试集写为函数,增强代码复用性

function (do_test target arg result)add_test(NAME Comp${arg} COMMAND ${target} ${arg})set_tests_properties(Comp${arg}PROPERTIES PASS_REGULAR_EXPRESSION "${arg} is ${result}")
endfunction()function (do_math_test target)do_test(${target} 4 2)do_test(${target} -25 "(-nan|nan|0)")
endfunction()
do_math_test(Tutorial)

Scripting Commands

  • cmake命令不区分大小写,不过小写命令更推荐使用
  • cmake 变量,参数等区分大小写

基础设置变量

使用set命令来设置变量:

set(<variable> <value>... [PARENT_SCOPE])
  • 如果value为空格分隔的字符串(不加引号),则被认为是列表
  • 列表也可以用"a;b"(以分号分隔,加引号)等效

CMakeLists 文件结构

通常情况下,CMakeLists文件结构如下所示:

cmake_minimum_required(VERSION 3.0)project(project_name)...
  • cmake_minimum_required指定了该项目生成需要的最小版本
  • project()指定项目名称,该命令以下部分都是该项目的配置

批量添加文件

aux_source_directory(<variable> <source_dir>)

此命令将添加source_dir下的所有匹配文件到variable中。(匹配文件根据项目语言决定

文件操作指令

  • file是cmake中的文件操作指令,可以完成复制、创建等一系列工作,也可以用于查找文件:

    file(GLOB <variable> CONFIGURE_DEPENDS <globbing-expressions>)
    
    • CONFIGURE_DEPENDS可以在文件更新时自动更新cmake
    • 后面是查找文件的表达式,可以是通配符,如*.cpp *.h
  • configure_file 可以完成文件配置,按照模板文件生成目标文件

    configure_file(Config.h.in ${PROJECT_SOURCE_DIR}/Config.h)
    

    该命令会将模板文件Config.h.in中内容替换为实际配置内容,并将头文件写入source目录下的Config.h中,这样,可以完成对文件内容的修改,如启用选项,编辑#define常量,或其他宏补全效果。

    常用模板格式如下:

    #define FOO_STR "@FOO_STR@"
    #cmakedefine FOO_ENABLE
    

    该命令会@号包含的部分转换为cmake 执行环境中变量,使用cmakedefine如果cmake环境中存在变量,则会将其修改为#define FOO_ENABLE

    即,如果在CMakeLists中设置

    set(FOO_STR "Hello world")
    option(FOO_ENABLE True)
    

    则模板文件中的定义将被输出为:

    #define FOO_STR "Hello world"
    #define FOO_ENABLE
    

输出字符串

使用message命令输出字符串

message([<mode>] "message text" ...)

其中模式可以为下列等:

  • STATUS 状态信息,前面带--
  • WARNING 警告信息,黄色警告
  • FATAL_ERROR 致命错误
  • INFO 默认,前面不带任何,白色,输出到stderr

列表 list

使用list命令来构建,操作列表

Readinglist(LENGTH <list> <out-var>)list(GET <list> <element index> [<index> ...] <out-var>)list(JOIN <list> <glue> <out-var>)list(SUBLIST <list> <begin> <length> <out-var>)Searchlist(FIND <list> <value> <out-var>)Modificationlist(APPEND <list> [<element>...])list(FILTER <list> {INCLUDE | EXCLUDE} REGEX <regex>)list(INSERT <list> <index> [<element>...])list(POP_BACK <list> [<out-var>...])list(POP_FRONT <list> [<out-var>...])list(PREPEND <list> [<element>...])list(REMOVE_ITEM <list> <value>...)list(REMOVE_AT <list> <index>...)list(REMOVE_DUPLICATES <list>)list(TRANSFORM <list> <ACTION> [...])Orderinglist(REVERSE <list>)list(SORT <list> [...])

详见list — CMake 3.25.1 Documentation,[下一小节](#选项 option)会有应用选项的列表操作

选项 option

使用option来生成选项,这些选项**会在ccmake**或cmake-gui中被显示

option(VAR_NAME [Description] [default_value])
  • option中的默认选项会被命令行中的-D选项覆盖

例如,

option(USE_MYMATH "Enable MyMath Library" True)

cmake-gui中,会显示如下,并可以被配置

image-20230116210855149

一般项目情形下,需要使用option来控制某个子功能是否启动,可以使用以下命令(接上例USE_MYMATH):

if (USE_MYMATH)add_subdirectory(MathFunctions)list(APPEND EXTRA_LIBS MathFunctions)list(APPEND EXTRA_INCLUDES MathFunctions)
endif()

如果选项中启用USE_MYMATH,才会进行库引用

生成器表达式

使用生成器表达式可以简化指令

$<$<var_name:value>:statement>

只有在变量=值时,才会表现为statement,否则,生成器表达式的值为空

变量与作用域

默认变量传播规则:parent->child

如果要child->parent,则增加选项PARENT_SCOPE

Usage Requirements

在外部引用项目时,需要满足一些特定条件,这些条件称为usage requirements

只要项目开发者编写Usage Requirements,使用者就可以直接通过link完成寻找包和链接功能,而不需要另外的配置(添加include等),是现代cmake的主要构成。

同时,这些引用也是会传递的,不需要进行额外配置(但要保证配置正确)

在配置项目时,一般有三种配置选项PRIVATE|PUBLIC|INTERFACE,其中,PRIVATE仅限于项目自身编译时使用,INTERFACE是Usage Requirements,它要求所有使用该库的项目添加该动作PUBLIC则是两者兼有。

例如,

add_library(MathFunctions mysqrt.cxx)
target_include_directories(MathFunctions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

以上指令会使所有引用该库(MathFunctions)的项目自动引用该项目的头文件

相关文章:

现代 cmake (cmake 3.x) 操作大全

cmake 是一个跨平台编译工具&#xff0c;它面向各种平台提供适配的编译系统配置文件&#xff0c;进而调用这些编译系统完成编译工作。cmake 进入3.x 版本&#xff0c;指令大量更新&#xff0c;一些老的指令开始被新的指令集替代&#xff0c;并加入了一些更加高效的指令/参数。本…...

how https works?https工作原理

简单一句话&#xff1a; https http TLShttps 工作原理&#xff1a;HTTPS (Hypertext Transfer Protocol Secure)是一种带有安全性的通信协议&#xff0c;用于在互联网上传输信息。它通过使用加密来保护数据的隐私和完整性。下面是 HTTPS 的工作原理&#xff1a;初始化安全会…...

Docker的资源控制管理

目录 一、CPU控制 1、设置CPU使用率上限 2、设置CPU资源占用比&#xff08;设置多个容器时才有效&#xff09; 3、设置容器绑定指定的CPU 二、对内存使用进行限制 1、创建指定物理内存的容器 2、创建指定物理内存和swap的容器 3、 对磁盘IO配额控制&#xff08;blkio&a…...

MMSeg无法使用单类自定义数据集训练

文章首发及后续更新&#xff1a;https://mwhls.top/4423.html&#xff0c;无图/无目录/格式错误/更多相关请至首发页查看。 新的更新内容请到mwhls.top查看。 欢迎提出任何疑问及批评&#xff0c;非常感谢&#xff01; 摘要&#xff1a;将三通道图像转为一通道图像&#xff0c;…...

Redis使用方式

一、Redis基础部分: 1、redis介绍与安装比mysql快10倍以上 *****************redis适用场合**************** 1.取最新N个数据的操作 2.排行榜应用,取TOP N 操作 3.需要精确设定过期时间的应用 4.计数器应用 5.Uniq操作,获取某段时间所有数据排重值 6.实时系统,反垃圾系统7.P…...

无主之地3重型武器节奏评分榜(9.25) 枪械名 红字效果 元素属性 清图评分 Boss战评分 泛用性评分 特殊性评分 最终评级 掉落点 掉率 图片 瘟疫传播

无主之地3重型武器节奏评分榜&#xff08;9.25&#xff09; 枪械名 红字效果 元素属性 清图评分 Boss战评分 泛用性评分 特殊性评分 最终评级 掉落点 掉率 图片 瘟疫传播者 发射巨大能量球&#xff0c;能量球会额外生成追踪附近敌人的伴生弹 全属性 SSS SSS SSS - T0 伊甸6号-…...

什么是编程什么是算法

1.绪论 编程应在一个开发环境中完成源程序的编译和运行。首先,发现高级语言开发环境,TC,Windows系统的C++,R语言更适合数学专业的学生。然后学习掌握编程的方法,在学校学习,有时间的人可以在网上学习,或者购买教材自学。最后,编写源程序,并且在开发环境中实践。 例如…...

【c++】函数

文章目录函数的定义函数的调用值传递常见样式函数的声明函数的分文件编写函数的作用&#xff1a; 将一段经常使用的代码封装起来&#xff0c;减少重复代码。 一个较大的程序&#xff0c;一般分为若干个程序块&#xff0c;每个模板实现特定的功能。 函数的定义 返回值类型 函数…...

[golang gin框架] 1.Gin环境搭建,程序的热加载,路由GET,POST,PUT,DELETE

一.Gin 介绍Gin 是一个 Go (Golang) 编写的轻量级 http web 框架&#xff0c;运行速度非常快&#xff0c;如果你是性能和高效的追求者&#xff0c;推荐你使用 Gin 框架.Gin 最擅长的就是 Api 接口的高并发&#xff0c;如果项目的规模不大&#xff0c;业务相对简单&#xff0c;这…...

【开源】祁启云网络验证系统V1.11

简介 祁启云免费验证系统 一个使用golang语言、Web框架beego、前端Naive-Ui-Admin开发的免费网络验证系统 版本 当前版本1.11 更新方法 请直接将本目录中的verification.exe/verification直接覆盖到你服务器部署的目录&#xff0c;更新前&#xff0c;请先关闭正在运行的验…...

震源机制(Focal Mechanisms)之沙滩球(Bench Ball)

沙滩球包含如下信息&#xff1a; a - 判断断层类型&#xff0c;可根据球的颜色快速判断 b - 判断断层的走向(strike)&#xff0c;倾角(dip) c - 确定滑移角/滑动角(rake) 走向 &#xff0c;倾角&#xff0c;滑移角 如不了解断层的定义&#xff0c;可以先阅读&#xff1a;震…...

C++入门:多态

多态按字面的意思就是多种形态。当类之间存在层次结构&#xff0c;并且类之间是通过继承关联时&#xff0c;就会用到多态。C 多态意味着调用成员函数时&#xff0c;会根据调用函数的对象的类型来执行不同的函数。1、纯虚函数声明如下&#xff1a; virtual void funtion1()0; 纯…...

华为OD真题_工位序列统计友好度最大值(100分)(C++实现)

题目描述 工位由序列F1,F2…Fn组成,Fi值为0、1或2。其中0代表空置,1代表有人,2代表障碍物。 1、某一空位的友好度为左右连续老员工数之和 2、为方便新员工学习求助,优先安排友好度高的空位 给出工位序列,求所有空位中友好度的最大值。 输入描述 第一行为工位序列:F1,F…...

[ruby on rails]MD5、SHA1、SHA256、Base64、aes-128-cbc、aes-256-ecb

md5 puts Digest::MD5.hexdigest(admin) sha1 require digest/sha1 puts Digest::SHA1.hexdigest(admin)base64 require base64 code Base64.encode64(admin) source Base64.decode64(code)aes-128-cbc # base64 解密数据 session_key Base64.decode64(session_ke…...

《NFL星计划》:拉斯维加斯突袭者·橄榄1号位

拉斯维加斯袭击者&#xff08;英语&#xff1a; Las Vegas Raiders&#xff09;又译拉斯维加斯侵略者或拉斯维加斯突击者&#xff0c;是一支主场位于美国内华达州拉斯维加斯的职业美式橄榄球球队&#xff0c;属全国橄榄球联盟 (NFL) 的美国橄榄球联合会 (AFC) 西区。实际上&…...

韩顺平Linux基础学习(1)

内容概括...

Rust学习入门--【6】Rust 基础语法

Rust 基础语法 变量&#xff0c;数据类型&#xff0c;注释&#xff0c;函数和控制流&#xff0c;这些是大部分编程语言都具有的编程概念。 本节将学习理解这些概念。 变量 Rust 是强类型语言&#xff0c;但具有自动判断变量类型的能力。这很容易让人与弱类型语言产生混淆。…...

LINUX提权入门手册

前言 发点存货 LINUX权限简介 在学习提权之前我们先了解一下linux里面的权限我们使用命令: ls -al即可查看列出文件所属的权限&#xff1a; 文件头前面都有一段类似的字符&#xff0c;下面我们仔细分析一下里面符号分别代表什么。 -rw-r--r-- 1 root root 第一个符号-的…...

MSI_MSI-X中断之源码分析

MSI_MSI-X中断之源码分析 文章目录MSI_MSI-X中断之源码分析一、 怎么发出MSI/MSI-X中断1.1 在RK3399上体验1.1.1 安装工具1.1.2 查看设备MSI-X信息1.1.3 验证MSI-X信息二、 怎么使用MSI/MSI-X三、 MSI/MSI-X中断源码分析3.1 IRQ Domain创建流程3.1.1 GIC3.1.2 ITS3.1.3 PCI MSI…...

Docker--consul

目录 前言 一、Consul 简介 1.1、 consul 概述 1.2 、consul 的两种模式 1.3、consul 提供的一些关键特性 二、Consul 容器服务更新与发现 三、consul 部署 3.2、查看集群信息 四、registrator服务器 consul-template 五、consul 多节点 前言 服务注册与发现是微服…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站&#xff0c;会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后&#xff0c;网站没有变化的情况。 不熟悉siteground主机的新手&#xff0c;遇到这个问题&#xff0c;就很抓狂&#xff0c;明明是哪都没操作错误&#x…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

基于Java+MySQL实现(GUI)客户管理系统

客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息&#xff0c;对客户进行统一管理&#xff0c;可以把所有客户信息录入系统&#xff0c;进行维护和统计功能。可通过文件的方式保存相关录入数据&#xff0c;对…...

Golang——9、反射和文件操作

反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一&#xff1a;使用Read()读取文件2.3、方式二&#xff1a;bufio读取文件2.4、方式三&#xff1a;os.ReadFile读取2.5、写…...