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

CMake基础【学习笔记(八)】

声明此博客为转载

CMake基础

文章目录

  • CMake基础
    • 一、准备知识
      • 1.1 C++的编译过程
      • 1.2 静态链接库和动态链接库
      • 1.3 为什么需要CMake
        • 1.3.1 g++ 命令行编译
        • 1.3.2 CMake简介
    • 二、CMake基础知识
      • 2.1 安装
      • 2.2 第一个CMake例子
      • 2.3 语法基础
        • 2.3.1 指定版本
        • 2.3.2 设置项目
        • 2.3.3 添加可执行文件目标
        • 2.3.4 生成静态库并链接
        • 2.3.5 生成动态库并连接
        • 2.3.6 CMake 中的 PUBLIC、PRIVATE、INTERFACE
        • 2.3.7 变量
        • 2.3.8 include引入其他代码
        • 2.3.9 条件控制
        • 2.3.10 CMake分步编译
        • 2.3.11 生成器表达式
        • 2.3.12 函数和宏
        • 2.3.13 设置安装
        • 2.3.14 寻找依赖 find_package
    • 三、opencv CMake示例

一、准备知识

1.1 C++的编译过程

使用g++等编译工具,从源码生成最终的可执行文件一般有这几步:预处理(Preprocess)、编译(Compile)、汇编(assemble)、链接(link)。

输入g++ --help可以看到对应命令:

-E                       Preprocess only; do not compile, assemble or link.
-S                       Compile only; do not assemble or link.
-c                       Compile and assemble, but do not link.
-o <file>                Place the output into <file>.

以下面程序为例:

#include <iostream>int main() {std::cout << "Hello World!" << std::endl;return 0;
}
  • 第一步:预处理
    C++中预处理指令以 # 开头。在预处理阶段,会对#define进行宏展开,处理#if,#else等条件编译指令,递归处理#include。这一步需要我们添加所有头文件的引用路径。

    # 将xx.cpp源文件预处理成xx.i文件(文本文件)
    g++ -E main.cpp -o main.i
    
  • 第二步:编译

    检查代码的规范性和语法错误等,检查完毕后把代码翻译成汇编语言文件。

    # 将xx.i文件编译为xx.s的汇编文件(文本文件)
    g++ -S main.i -o main.s
    
  • 第三步:汇编
    基于汇编语言文件生成二进制格式的目标文件。

    # 将xx.s文件汇编成xx.o的二进制目标文件
    g++ -c main.s -o main.o
    
  • 第四步:链接

    将目标代码与所依赖的库文件进行关联或者组装,合成一个可执行文件

    # 将xx.o二进制文件进行链接,最终生成可执行程序
    g++ main.o -o main
    

1.2 静态链接库和动态链接库

所谓静态和动态,其区别是链接的阶段不一样。

  • 静态链接库名称一般是lib库名称.a.a代表archive library),其链接发生在编译环节。一个工程如果依赖一个静态链接库,其输出的库或可执行文件会将静态链接库*.a打包到该工程的输出文件中(可执行文件或库),因此生成的文件比较大,但在运行时也就不再需要库文件了。

  • 而动态链接库的链接发生在程序的执行过程中,其在编译环节仅执行链接检查,而不进行真正的链接,这样可以节省系统的开销。动态库一般后缀名为*.so.so代表shared object,Linux:lib库名称.so ,macOS:lib库名称.dylib)。动态链接库加载后,在内存中仅保存一份拷贝,多个程序依赖它时,不会重复加载和拷贝,这样也节省了内存的空间。

  • 以下图为例

    • 工程AB依赖静态链接库 static libraryAB在运行时,内存中会有多份static library

    • 工程AB依赖动态链接库 shared libraryAB在运行时,内存中只有一份 shared library(shared:共享)。

以上只是非常简单的一个解释以区分动态链接库和静态链接库。更多底层的知识需要单独进行深入讲解。

1.3 为什么需要CMake

1.3.1 g++ 命令行编译

当我们编译附件中1.hello_world时,我们可以运行

g++ main.cpp -o main

当我们需要引入外部库时,如附件中的2.external_libs,需要引入gflags(Google开源的命令行参数处理库),我们则需要运行:

# 安装gflags
sudo apt-get install libgflags-dev libgflags2.2 // -lgflags表示链接gflags库,-o main表示输出文件名为main
g++ main.cpp -lgflags -o main # 或者:# 安装pkg-config
sudo apt-get install pkg-config// pkg-config是一个工具,用于查找和管理安装在系统上的库文件,--cflags --libs gflags表示查找gflags库的头文件和库文件的路径,-o main表示输出文件名为maing++ main.cpp `pkg-config --cflags --libs gflags`  -o main # 测试输出
./main --age 31 --name alice

有些时候有一些常用库我们也不用手动添加头文件或链接库路径,通常g++能在默认查询路径中找到他们。当我们的项目文件变得多起来,引入的外部库也多起来时,命令行编译这种方式就会变得十分臃肿,也不方便调试和编辑。通常在测试单个文件时会使用命令行进行编译,但不推荐在一个实际项目中使用命令行编译。

1.3.2 CMake简介

在实际工作中推荐使用CMake构建C++项目,CMake是用于构建、测试和软件打包的开源跨平台工具;

特性:

  • 自动搜索可能需要的程序、库和头文件的能力;
  • 独立的构建目录(如build),可以安全清理
  • 支持复杂的自定义命令(下载、生成各种文件)
  • 自定义配置可选组件
  • 从简单的文本文件(CMakeLists.txt)自动生成工作区和项目的能力
  • 在主流平台上自动生成文件依赖项并支持并行构建
  • 几乎支持所有的IDE

二、CMake基础知识

2.1 安装

ubuntu上请执行,但是版本不一定是最新版,

sudo apt install cmake -y

或者编译安装:

# 以v3.25.1版本为例
git clone -b v3.25.1 https://github.com/Kitware/CMake.git 
cd CMake
# 你使用`--prefix`来指定安装路径,或者去掉`--prefix`,安装在默认路径。
./bootstrap --prefix=<安装路径> && make && sudo make install# 验证
cmake --version

2.2 第一个CMake例子

附件位置:3.first_cmake

# 第一步:配置,-S 指定源码目录,-B 指定构建目录
cmake -S . -B build 
# 第二步:生成,--build 指定构建目录
cmake --build build
# 运行
./build/first_cmake

vs code插件:

  • 安装twxs.cmake做代码提示;
  • 安装ms-vscode.cmake-tools界面操作。

2.3 语法基础

2.3.1 指定版本

以附件:3.first_cmake/CMakeLists.txt为例:

# CMake 最低版本号要求
cmake_minimum_required(VERSION 3.10)# first_cmake是项目名称,VERSION是版本号,DESCRIPTION是项目描述,LANGUAGES是项目语言
project(first_cmake VERSION 1.0.0 DESCRIPTION "项目描述"LANGUAGES CXX) # 添加一个可执行程序,first_cmake是可执行程序名称,main.cpp是源文件
add_executable(first_cmake main.cpp)

命令cmake_minimum_required来指定当前工程所使用的CMake版本,不区分大小写的,通常用小写。VERSION是这个函数的一个特殊关键字,版本的值在关键字之后。CMake中的命令大多和cmake_minimum_required相似,不区分大小写,并有很多关键字来引导命令的参数输入(类似函数传参)。

2.3.2 设置项目

以附件:3.first_cmake/CMakeLists.txt为例:

project(ProjectName VERSION 1.0.0 DESCRIPTION "项目描述"LANGUAGES CXX) 

CMakeLists.txt的开头,都会使用project来指定本项目的名称、版本(注意:是自己项目的版本)、介绍、与使用的语言。在project中,第一个ProjectName(例子中用的是first_cmake)不需要参数,其他关键字都有参数。

2.3.3 添加可执行文件目标

以附件:3.first_cmake/CMakeLists.txt为例:

add_executable(first_cmake main.cpp)

这里我们用到add_executable,其中第一个参数是最终生成的可执行文件名以及在CMake中定义的Target名。我们可以在CMake中继续使用Target的名字为Target的编译设置新的属性和行为。命令中第一个参数后面的参数都是编译目标所使用到的源文件。

2.3.4 生成静态库并链接

附件位置:4.static_lib_test,其中文件夹 account_dir 是创建静态链接库,test_account 文件夹是调用静态链接库, CMakeLists.txt 是用来生成相应的静态库,

A.生成静态库

add_library(Account STATIC Account.cpp Account.h) 参数解释:Account:库的名称,STATIC :用于指定链接库为动态链接库(SHARED)还是静态链接库(STATIC),Account.cpp Account.h:用的源码的路径,

#account_dir/CMakeLists.txt# 最低版本要求
cmake_minimum_required(VERSION 3.10)# 项目信息
project(Account)# 添加静态库,Linux下会生成libAccount.a
add_library(Account STATIC Account.cpp Account.h)
# 编译静态库后,会在build下生成 build/libAccount.a 静态库文件
account_dir/
├── Account.cpp
├── Account.h
├── build
│   └── libAccount.a
└── CMakeLists.txt

这里我们用到add_library, 和add_executable一样,Account为最终生成的库文件名(lib库名称.a),第二个参数是用于指定链接库为动态链接库(SHARED)还是静态链接库(STATIC),后面的参数是需要用到的源文件。

B.链接

# test_account/CMakeLists.txt# 最低版本要求
cmake_minimum_required(VERSION 3.10)# 项目名称
project(test_account)# 添加执行文件
add_executable(test_account test_account.cpp)# 添加头文件目录,如果不添加,找不到头文件
target_include_directories(test_account PUBLIC "../account_dir")
# 添加库文件目录,如果不添加,找不到库文件
target_link_directories(test_account PUBLIC "../account_dir/build")
# 添加目标链接库
target_link_libraries(test_account PRIVATE Account)
# 编译后目录如下
4.static_lib_test/
├── account_dir
│   ├── Account.cpp
│   ├── Account.h
│   ├── build
│   │   └── libAccount.a
│   └── CMakeLists.txt
└── test_account ├── build│   └── test_account├── CMakeLists.txt└── test_account.cpp

我们通过add_libraryadd_executable定义了Target,我们可以通过Target的名称为其添加属性,例如:

# 指定目标包含的头文件目录
target_include_directories(test_account PUBLIC "../account_dir")
# 添加库文件目录,如果不添加,找不到库文件
target_link_directories(test_account PUBLIC "../account_dir/build")
# 指定目标链接的库
target_link_libraries(test_account PRIVATE Account)
  • 通过target_include_directories,我们给test_account添加了头文件引用路径"../account_dir"。上面的关键词PUBLIC,PRIVATE用于说明目标属性的作用范围,更多介绍参考下节。
  • 通过target_link_libraries,将前面生成的静态库libAccount.a链接给对象test_account,但此时还没指定库文件的目录,CMake无法定位库文件
  • 再通过target_link_directories,添加库文件的目录即可。
2.3.5 生成动态库并连接

附件位置:5.dynamic_lib_test

A.生成动态库

#account_dir/CMakeLists.txt# 添加动态库,Linux下会生成libAccount.so
add_library(Account SHARED Account.cpp Account.h)
# 编译动态库后,会在build下生成 build/libAccount.so 动态库文件
account_dir/
├── Account.cpp
├── Account.h
├── build
│   └── libAccount.so
└── CMakeLists.txt

B.链接

操作不变。

# ldd查看依赖的动态库
libAccount.so => /home/enpei/Documents/course_cpp_tensorrt/course_5/src/5.dynamic_lib_test/test_account/../account_dir/build/libAccount.so (0x00007fb692cf1000)

当然,也可以用一个CMakeLists.txt来一次性编译,参考附件6.build_together

#6.build_together/CMakeLists.txt`# 最低版本要求
cmake_minimum_required(VERSION 3.10)# 项目信息
project(test_account)# 添加动态库
add_library(Account SHARED "./account_dir/Account.cpp" "./account_dir/Account.h")# 添加可执行文件
add_executable(test_account "./test_account/test_account.cpp")# 添加头文件
target_include_directories(test_account PUBLIC "./account_dir")
# 添加链接库
target_link_libraries(test_account Account)
2.3.6 CMake 中的 PUBLIC、PRIVATE、INTERFACE

CMake中经常使用target_...()类似的命令,一般这样的命令支持通过PUBLICPRIVATEINTERFACE关键字来控制传播。

target_link_libraries(A B)为例,从理解的角度来看

  • PRIVATE :依赖项B仅链接到目标 A,如果有C 链接了AC不会链接B
  • INTERFACE :依赖项B并不链接到目标A,如果有C 链接了AC会链接B
  • PUBLIC :依赖项B链接到目标 A,如果有C 链接了AC也会链接B

其实就是对象属性的传递,打个散烟的比方:

  • PRIVATE: 就是自己抽,不给别人抽
  • INTERFACE :就是自己不抽,给别人抽
  • PUBLIC :就是自己抽,也给别人抽

从使用的角度来说,如果有C链接了目标A

  • 如果B仅用于A的实现,且不在头文件中提供给C使用,使用PRIVATE
  • 如果B不用于A的实现,仅在头文件中作为借口给C使用,使用INTERFACE
  • 如果B既用于A的实现,也在头文件中提供给C使用,使用PUBLIC

举例:

# 创建库
add_library(C c.cpp)
add_library(D d.cpp)
add_library(B b.cpp)# C是B的PUBLIC依赖项
target_link_libraries(B PUBLIC C)
# D是B的PRIVATE依赖项
target_link_libraries(B PRIVATE D)# 添加可执行文件
add_executable(A a.cpp)# 将B链接到A
target_link_libraries(A B)
  • 因为CBPUBLIC依赖项,所以C会传播到A
  • 因为DBPRIVATE依赖性,所以D不会传播到A
2.3.7 变量

附件位置:7.message_var_demo

像其他编程语言一样,我们应该将CMake理解为一门编程语言。我们也需要设定变量来储存我们的选项,信息。有时候我们通过变量来判断我们在什么平台上,通过变量来判断我们需要编译哪些Target,也通过变量来决定添加哪些依赖。

2.3.8 include引入其他代码

附件位置:8.include_demo

2.3.9 条件控制

附件位置:9.if_demo

正如前面所讲,应该把CMake当成编程语言,除了可以设置变量以外,CMake还可以写条件控制。

if(variable)# 为true的常量:ON、YES、TRUE、Y、1、非0数字
else()# 为false的常量:OFF、NO、FALSE、N、0、空字符串、NOTFOUND
endif()

可以和条件一起使用的关键词有

NOT, TARGET, EXISTS (file), DEFINED等
STREQUAL, AND, OR, MATCHES (regular expression), VERSION_LESS, VERSION_LESS_EQUAL等
2.3.10 CMake分步编译

附件位置:10.steps_demo

# 查看所有目标
$ cmake -S . -B build
$ cd build
$ cmake --build . --target helpThe following are some of the valid targets for this Makefile:
... all (the default if no target is provided)
... clean
... depend
... rebuild_cache
... edit_cache
... steps_demo
... main.o
... main.i
... main.s# 1.预处理
$ cmake --build . --target main.i
# 输出:Preprocessing CXX source to CMakeFiles/steps_demo.dir/main.cpp.i
# 可以打开滑到底部# 2.编译
$ cmake --build . --target main.s
# 输出汇编代码:Compiling CXX source to assembly CMakeFiles/steps_demo.dir/main.cpp.s# 3.汇编
$ cmake --build . --target main.o
# 输出二进制文件:Building CXX object CMakeFiles/steps_demo.dir/main.cpp.o# 链接
$ cmake --build .
Scanning dependencies of target steps_demo
[ 50%] Linking CXX executable steps_demo
[100%] Built target steps_demo# 运行
./steps_demo
2.3.11 生成器表达式

附件位置:11.generator_expression

生成器表达式简单来说就是在CMake生成构建系统的时候根据不同配置动态生成特定的内容。有时用它可以让代码更加精简,我们介绍几种常用的。

需要注意的是,生成表达式被展开是在生成构建系统的时候,所以不能通过解析配置CMakeLists.txt阶段的message命令打印,可以用类似file(GENERATE OUTPUT "./generator_test.txt" CONTENT "$<$<BOOL:TRUE>:TEST>")生成文件的方式间接测试。

在其最一般的形式中,生成器表达式是$<...>,尖括号中间可以是如下几种类型:

  • 条件表达式
  • 变量查询(Variable-Query)
  • 目标查询(Target-Query)
  • 输出相关的表达式
# 1.条件表达式:$<condition:true_string>,当condition为真时,返回true_string,否则返回空字符串
$<0:TEST>  
$<1:TEST>  
$<$<BOOL:TRUE>:TEST># 2.变量查询(Variable-Query)
$<TARGET_EXISTS:target>:判断目标是否存在
$<CONFIG:Debug>:判断当前构建类型是否为Debug# 3.目标查询(Target-Query)
$<TARGET_FILE:target>:获取编译目标的文件路径
$<TARGET_FILE_NAME:target>:获取编译目标的文件名

4.输出相关表达式:用于在不同的环节使用不同参数,比如需要在installbuild环节分别用不同的参数,我们可以这样写:

add_library(Foo ...)
target_include_directories(FooPUBLIC$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)

其中$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>仅在build环节生效;而$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>仅在install环节生效。通过设定不同阶段不同的参数,我们可以避免路径混乱的问题。

2.3.12 函数和宏

附件位置:12.function_macro

# 定义一个宏,宏名为my_macro,没有参数
macro(my_macro)message("宏内部的信息")set(macro_var "宏内部变量test")
endmacro(my_macro)# 定义一个函数,函数名为second_func,有两个参数
function(second_func arg1 arg2)message("第一个参数:${arg1}, 第二个参数:${arg2}")
endfunction(second_func)
2.3.13 设置安装

附件位置:13.install_demo

当需要发布项目时你需要指定项目文件的安装路径。下面的代码片段中,使用install安装demo_test,并分别将可执行文件安装在bin中,动态链接库和静态链接库都安装在lib,公共头文件安装在include。这里的路径都将添加${CMAKE_INSTALL_PREFIX}作为前缀(如果不设置CMAKE_INSTALL_PREFIX,则会安装到/usr/local 目录下)。实现安装的功能在你需要发布你项目给其他人使用时,非常有用。

# 设置安装
install(TARGETS demo_testRUNTIME DESTINATION bin # 可执行文件LIBRARY DESTINATION lib # 动态库ARCHIVE DESTINATION lib # 静态库PUBLIC_HEADER DESTINATION include # 公共头文件
)
2.3.14 寻找依赖 find_package

对于大部分支持了CMake的项目来说,均可以通过find_package找到对应的依赖库,参考附件:14.find_demo

# 使用find_package寻找<LibaryName>库,如果找到,一般都会有以下变量(库作者设置)
<LibaryName>_FOUND:表示是否找到
<LibaryName>_INCLUDE_DIR:表示头文件目录
<LibaryName>_LIBRARIES:表示库文件目录

假设我们编写了一个新的函数库,我们希望别的项目可以通过find_package对它进行引用,我们有两种办法:

  • 编写一个Find<LibraryName>.cmake,适用于导入非cmake安装的项目,参考附件:15.custom_find
  • 使用install安装,生成<LibraryName>Config.cmake文件,适用于导入自己开发的cmake项目,参考附件:16.custom_install_demo

三、opencv CMake示例

附件位置:17.demo_opencv/

安装OpenCV:sudo apt install libopencv-dev

依赖和链接OpenCV与常规的添加依赖并没有太多不同,同时OpenCV提供了cmake find package的功能,因此我们可以通过find_package方便的定位opencv在系统中的位置和需要添加的依赖。

find_package(OpenCV REQUIRED)message("OPENCV INCLUDE DIRS: ${OpenCV_INCLUDE_DIRS}")
message("OPENCV LINK LIBRARIES: ${OpenCV_LIBS}")

如果cmake找到了OpenCV,配置cmake后,命令行会有如下输出:

OPENCV INCLUDE DIRS: /usr/include/opencv4
OPENCV LINK LIBRARIES: opencv_calib3d;opencv_core;opencv_dnn;opencv_features2d;opencv_flann;opencv_highgui;opencv_imgcodecs;opencv_imgproc;opencv_ml;opencv_objdetect;opencv_photo;opencv_stitching;opencv_video;opencv_videoio;opencv_aruco;opencv_bgsegm;opencv_bioinspired;opencv_ccalib;opencv_datasets;opencv_dnn_objdetect;opencv_dnn_superres;opencv_dpm;opencv_face;opencv_freetype;opencv_fuzzy;opencv_hdf;opencv_hfs;opencv_img_hash;opencv_line_descriptor;opencv_optflow;opencv_phase_unwrapping;opencv_plot;opencv_quality;opencv_reg;opencv_rgbd;opencv_saliency;opencv_shape;opencv_stereo;opencv_structured_light;opencv_superres;opencv_surface_matching;opencv_text;opencv_tracking;opencv_videostab;opencv_viz;opencv_ximgproc;opencv_xobjdetect;opencv_xphoto

相关文章:

CMake基础【学习笔记(八)】

声明此博客为转载 CMake基础 文章目录 CMake基础一、准备知识1.1 C的编译过程1.2 静态链接库和动态链接库1.3 为什么需要CMake1.3.1 g 命令行编译1.3.2 CMake简介 二、CMake基础知识2.1 安装2.2 第一个CMake例子2.3 语法基础2.3.1 指定版本2.3.2 设置项目2.3.3 添加可执行文件…...

异常的学习

异常分为编译时期异常与运行时期异常 编译时期异常运行前必须处理&#xff0c;否则代码报错 除了RuntimeException和他的子类&#xff0c;其他都是编译时异常 运行时期异常运行时报错&#xff0c;一般是由参数传递错误导致的报错 异常的作用&#xff1a; 1.异常使用来查询b…...

【洛谷 P1101】单词方阵 题解(深度优先搜索)

单词方阵 题目描述 给一 n n n \times n nn 的字母方阵&#xff0c;内可能蕴含多个 yizhong 单词。单词在方阵中是沿着同一方向连续摆放的。摆放可沿着 8 8 8 个方向的任一方向&#xff0c;同一单词摆放时不再改变方向&#xff0c;单词与单词之间可以交叉&#xff0c;因此…...

教师减负神器

在传统的成绩管理模式中&#xff0c;教师需要手动输入、整理、分析成绩数据&#xff0c;工作量大且繁琐。这不仅耗费了教师大量的时间和精力&#xff0c;还容易出现错误。为了解决这个问题&#xff0c;我们可以通过各种代码和Excel来实现学生自助查询成绩的功能。 一、建立成绩…...

Web 开发之前的一些话

我主要是对单页面进行开发&#xff0c;因而VUEFlask的搭配足以满足我的需求&#xff1b; VUE Vue.js - 渐进式 JavaScript 框架 | Vue.js Element-UI Element - The worlds most popular Vue UI framework FLASK 欢迎来到 Flask 的世界 — Flask中文文档(2.3.x)...

git快速入门!!! git的常用命令!!!

git快速入门 git的常用命令1. 初始化一个新的 Git 仓库2. 添加文件到暂存区3. 提交更改4. 查看当前分支的状态5. 创建并切换到新的分支6. 切换回之前的分支7. 合并分支8. 拉取远程仓库的更新9. 推送本地仓库的更新 git remote -v是什么git fetchclone命令详解push指定的分支git…...

C++并发编程实战——01.并发与并行

文章目录 并发并行及其使用原因并发与并行使用与不使用并发的原因C多线程支持 并发并行及其使用原因 本书相关 github翻译地址本书源码下载地址第一版github 翻译地址英文原版PDF不错的笔记所有实例的源代码&#xff0c;可在出版商的网站上进行下载github上下载源码 路线图 …...

PLC如何远程控制、调试?贝锐蒲公英二层组网功能一招搞定

在制造、交通、能源、采矿等领域&#xff0c;工业物联网是热门话题&#xff0c;各类采集、控制器、控制传感器通过网络互联&#xff0c;实现信息实时共享、交互后&#xff0c;不仅能快速了解生产过程数据&#xff0c;还能用于设备远程、调试维护等场景&#xff0c;对优化生产过…...

【大数据】-- flink kubernetes operator 入门与实践

课程链接:https://edu.csdn.net/course/detail/38831 目录 课程链接:https://edu.csdn.net/course/detail/38831https://edu.csdn.net/course/detail/38831 一、你将收获...

网络安全在代理技术中的实现与应用

随着互联网技术的飞速发展&#xff0c;网络安全日益受到人们的重视。在这个背景下&#xff0c;代理技术成为了网络安全实现的重要手段之一。本文将针对 SOCKS5 代理、SK5 代理、IP 代理等代理技术&#xff0c;探讨它们在网络安全和爬虫应用中的重要性&#xff0c;并介绍 HTTP 协…...

Nginx搭配负载均衡和动静分离:构建高性能Web应用的完美组合

目录 前言 一、Nginx简介 1.Nginx是什么 2.Nginx的特点 3.Nginx在哪使用 4.如何使用Nginx 5.Nginx的优缺点 6.Nginx的应用场景 二、负载均衡和动静分离 1.负载均衡 2.动静分离 三、Nginx搭载负载均衡并提供前后端分离后台接口数据 1.Nginx安装 2.tomcat负载均衡 …...

windows 运行 Mysql Command Line Client 自动关闭闪退原因分析

目录 原因分析一 原因分析二 原因分析三 第一次使用 MySQL Command Line Client 有可能输入密码后一按下回车键&#xff0c;程序窗口就自动关闭&#xff0c;出现闪退现象。本节主要分析产生闪退现象的原因以及如何处理这种情况。 原因分析一 首先可以查看程序默认执行文件…...

在CATIA工程制图中自动生成尺寸

然后微调即可...

蓝桥杯 (C++ 求和 等差数列 顺子日期 灌溉)

目录 1、求和 题目&#xff1a; 思路&#xff1a; 代码&#xff1a; 2、等差数列 题目&#xff1a; 思路&#xff1a; 代码&#xff1a; 3、顺子日期 题目&#xff1a; 思路&#xff1a; 代码&#xff1a; 4、灌溉 题目&#xff1a; 代码&#xff1a; 1、求和…...

Spring AOP基于XML方式笔记整理

XML AOP 加载流程 ClassPathXmlApplicationContext#refreshAbstractApplicationContext#obtainFreshBeanFactoryAbstractRefreshableApplicationContext#refreshBeanFactory创建DefaultListableBeanFactoryAbstractApplicationContext#loadBeanDefinitions(beanFactory)创建Xm…...

Docker HTTP(S) Proxy代理方式连接互联网

Docker HTTP(S) Proxy 是一种在 Docker 容器内部设置 HTTP(S) 代理的方法&#xff0c;以便于容器内的应用程序可以方便地通过代理访问互联网。设置 HTTP(S) 代理的方法主要有两种&#xff1a;使用 Dockerfile 配置和在使用 docker run 时添加参数。 以下是使用 Docker HTTP(S) …...

华纳云:centos系统中怎么查看cpu信息?

在CentOS系统中&#xff0c;我们可以使用一些命令来查看CPU的详细信息。下面介绍几个常用的命令&#xff1a; 1. lscpu lscpu命令可以显示CPU的架构、型号、核心数、线程数、频率等信息。 # lscpu 执行以上命令后&#xff0c;会输出类似以下内容&#xff1a; 2. cat /proc/…...

如何选择微信管理系统?

如何选择微信管理系统&#xff1f; 1、不用下载安装软件&#xff0c;不越狱不刷机 2、不绑定手机或电脑&#xff0c;不对电脑或手机做限制&#xff0c;也不受电脑、手机关闭、关机影响 3、能更新迭代&#xff0c;不限制版本 4、使用安全登录&#xff0c;保障账号安全的 5、不用…...

文字的力量

不知道以前的时代的年轻人有没有这样的感受。现在我觉得自己是不是出现了认知偏差&#xff0c;发现在很多描写现在的二十几岁年轻人的成长经历的文字下面都会出现很多共鸣&#xff0c;包括我自己也有&#xff0c;就让我有一个错觉:是不是中国所有的和我同龄的年轻人都是这样过来…...

荒野大镖客emp.dll文件丢失的怎么办,快速修复游戏dll问题

在玩荒野大镖客这款游戏的过程中&#xff0c;我遇到了一个令人困扰的问题——emp.dll文件丢失。emp.dll是荒野大镖客游戏中的一个动态链接库文件&#xff0c;它负责管理游戏中的一些功能模块。当这个文件丢失时&#xff0c;游戏可能无法正常运行&#xff0c;导致一些功能无法使…...

后进先出(LIFO)详解

LIFO 是 Last In, First Out 的缩写&#xff0c;中文译为后进先出。这是一种数据结构的工作原则&#xff0c;类似于一摞盘子或一叠书本&#xff1a; 最后放进去的元素最先出来 -想象往筒状容器里放盘子&#xff1a; &#xff08;1&#xff09;你放进的最后一个盘子&#xff08…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

AtCoder 第409​场初级竞赛 A~E题解

A Conflict 【题目链接】 原题链接&#xff1a;A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串&#xff0c;只有在同时为 o 时输出 Yes 并结束程序&#xff0c;否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...