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

ROS 2中,CMakeList.txt常见语法

在ROS 2中,CMakeList.txt 文件扮演着配置和管理构建过程的重要角色。这个文件遵循CMake的语法,用于定义如何编译和链接源代码。下面是一些在ROS 2项目CMakeList.txt文件中常见的语法和用法。

1. 基本结构和命令

cmake_minimum_required(VERSION ):指定CMake的最低版本要求。
project():定义项目的名称,这个名称会用于构建过程中生成的目录和变量。

2. 查找和包含ROS 2的CMake宏

find_package(ament_cmake REQUIRED COMPONENTS …):查找ament_cmake包,这是ROS 2中用于包管理的CMake工具集。COMPONENTS后列出你需要的ament_cmake组件,比如dependencies、tests等。
find_package(rclcpp REQUIRED):查找并包含rclcpp包,rclcpp是ROS 2的C++客户端库。REQUIRED表明这个包是必需的,如果找不到则CMake会报错。

3. 添加源文件

set(CMAKE_CXX_STANDARD 14)(或更高版本):设置C++标准。
add_executable( …):添加一个可执行文件目标。是构建后生成的可执行文件的名称, …是构成该可执行文件的源文件列表。
add_library( SHARED|STATIC …):添加一个库目标。可以是共享库(SHARED)或静态库(STATIC)。

4. 链接库

target_link_libraries( <PRIVATE|INTERFACE|PUBLIC> …):为指定的目标(可执行文件或库)链接库。PRIVATE、INTERFACE、PUBLIC指定了链接属性的可见性。

5. 设置编译选项和依赖

ament_target_dependencies( …):为ament管理的目标(如ROS 2包)添加依赖。这确保了这些依赖在构建你的包之前被构建。
if(DEFINED ENV{}) 和 else()、endif():条件语句,可以根据环境变量或CMake变量的值来决定是否执行某些操作。

6. 安装目标和文件

install(TARGETS DESTINATION

):安装指定的目标(如可执行文件或库)到指定的目录。
install(FILES … DESTINATION ):安装指定的文件到指定的目录。

7. ROS 2特有的CMake宏

ROS 2还提供了一些特有的CMake宏,如:

ament_package():标记这个CMakeLists.txt定义的是一个ament包,用于ROS 2的包管理。
rosidl_generate_interfaces(…):自动生成ROS 2消息、服务和动作的接口代码。
ament_auto_add_library 是 ROS 2 中 ament_cmake_auto 包提供的一个宏,用于简化 CMakeLists.txt 文件中添加库的过程。这个宏结合了多个 CMake 命令的功能,使得添加库变得更加简单和直观。以下是 ament_auto_add_library 的基本用法:

8 ament_auto_add_library 基本语法

ament_auto_add_library(<library_name> [SHARED|STATIC|MODULE|INTERFACE|OBJECT] <source_files> ...)
  • <library_name>:你想要创建的库的目标名称。
  • [SHARED|STATIC|MODULE|INTERFACE|OBJECT]:指定库的类型。如果不指定,默认为 SHARED(共享库)。
  • <source_files> ...:构成库的源文件列表。

使用示例

假设你有一个 ROS 2 包,其中包含了一些 C++ 源文件,你想要将它们编译成一个共享库。你的 CMakeLists.txt 文件可能看起来像这样:

cmake_minimum_required(VERSION 3.5)
project(my_ros2_package)# 查找并包含ament_cmake_auto包
find_package(ament_cmake_auto REQUIRED)# 自动查找构建依赖
ament_auto_find_build_dependencies()# 添加库
ament_auto_add_library(my_library SHAREDsrc/my_library.cppinclude/my_library/my_library.hpp
)# 打包ament包
ament_auto_package()

在这个例子中,ament_auto_add_library 宏被用来创建一个名为 my_library 的共享库,它包含了 src/my_library.cpp 源文件和 include/my_library/my_library.hpp 头文件。ament_auto_find_build_dependencies() 宏用于自动查找并包含构建这个库所需的依赖项。最后,ament_auto_package() 宏用于打包这个 ament 包,以便它可以被 ROS 2 的包管理系统识别和使用。

优点

  • 简化 CMakeLists.txtament_auto_add_library 宏减少了需要编写的 CMake 命令数量,使得 CMakeLists.txt 文件更加简洁易读。
  • 自动处理依赖:通过 ament_auto_find_build_dependencies() 宏,ament_auto_add_library 能够自动查找并包含构建库所需的依赖项,减少了手动查找和包含依赖的麻烦。
  • 提高构建效率:由于 ament_cmake_auto 提供了许多自动化功能,因此它可以提高 ROS 2 包的构建效率。

注意事项

  • 确保你的 ROS 2 环境已经安装了 ament_cmake_auto 包。
  • 在使用 ament_auto_add_library 之前,需要调用 find_package(ament_cmake_auto REQUIRED) 来查找并包含这个包。
  • 如果你的库依赖于其他 ROS 2 包或第三方库,请确保在调用 ament_auto_add_library 之前使用 find_package() 命令来查找这些依赖项。然而,对于 ROS 2 包内的依赖项,ament_auto_find_build_dependencies() 宏通常能够自动处理。

9 rclcpp_components_register_node的用法

rclcpp_components_register_node 是 ROS 2 中用于注册组件式节点的一个宏,它允许你将一个类作为组件注册到 ROS 2 的组件容器中。这样,你就可以在运行时动态地加载、卸载和重新配置这些组件,而无需重新编译整个系统。这对于构建模块化、可扩展的 ROS 2 应用程序非常有用。

然而,需要注意的是,rclcpp_components_register_node 宏本身并不是 ROS 2 API 的一部分,或者至少不是以这种方式直接使用的。实际上,你可能是在寻找如何使用 rclcpp::Node 派生类与 ROS 2 组件系统结合的方法。

在 ROS 2 中,注册组件通常涉及以下几个步骤:

  1. 定义组件类:首先,你需要定义一个从 rclcpp::Node 派生的类,并在这个类中实现你的逻辑。但是,对于组件,你通常会从 rclcpp_components::NodeComponentrclcpp_lifecycle::LifecycleNode(如果你还需要生命周期管理)派生。

  2. 注册组件:然后,你需要使用 rclcpp_components 提供的宏(如 RCLCPP_COMPONENTS_REGISTER_NODE)来注册你的组件。这个宏会在编译时生成必要的代码,以便 ROS 2 的组件容器能够识别并加载你的组件。

  3. 在组件容器中加载组件:最后,你可以使用 ROS 2 的组件客户端(如 rclcpp_components::ComponentClient)来在运行时加载你的组件。

示例

下面是一个简化的示例,展示了如何定义一个组件并注册它:

#include "rclcpp/rclcpp.hpp"
#include "rclcpp_components/register_node_macro.hpp"// 假设我们有一个简单的组件类
class MyComponent : public rclcpp::NodeComponent {
public:explicit MyComponent(rclcpp::Node::SharedPtr node): NodeComponent(node) {// 初始化代码RCLCPP_INFO(this->get_logger(), "MyComponent initialized");}// 组件的其他成员函数...
};// 使用 RCLCPP_COMPONENTS_REGISTER_NODE 宏注册组件
// 注意:这里的宏参数需要根据你的包名和组件类名进行调整
RCLCPP_COMPONENTS_REGISTER_NODE(my_package::MyComponent)// 注意:上面的宏调用实际上是在内部生成了一些代码,
// 这些代码会在编译时添加到你的库中,以便 ROS 2 的组件系统能够识别它。
// 你不需要(也不应该)在你的代码中直接调用这个宏生成的任何函数或类。

注意RCLCPP_COMPONENTS_REGISTER_NODE 宏的确切用法可能会根据你的 ROS 2 版本和配置有所不同。上面的示例是一个简化的表示,旨在说明概念。在实际应用中,你可能需要查阅 ROS 2 的官方文档或源代码来获取准确的宏用法和参数。

此外,如果你的组件需要生命周期管理,你可能需要从 rclcpp_lifecycle::LifecycleNode 派生,并使用 rclcpp_lifecycle::register_node_macro 宏进行注册。但是,这通常涉及到更复杂的设置,包括定义生命周期状态和转换。

10 ament_auto_package 用法

ament_auto_package 是 ROS 2 中 ament_cmake_auto 包提供的一个宏,用于简化 CMakeLists.txt 文件中与包打包相关的操作。这个宏封装了多个 CMake 命令,以便在 ROS 2 包的构建过程中自动执行必要的打包步骤。

基本用法

在 CMakeLists.txt 文件的末尾调用 ament_auto_package() 宏,通常是在添加了所有可执行文件、库和测试之后。这个宏会处理与包打包相关的各种任务,如生成必要的配置文件、安装头文件和库文件等。

示例

以下是一个使用 ament_auto_package 宏的 CMakeLists.txt 文件的示例片段:

cmake_minimum_required(VERSION 3.5)
project(my_ros2_package)# 查找并包含ament_cmake_auto包
find_package(ament_cmake_auto REQUIRED)# 自动查找构建依赖
ament_auto_find_build_dependencies()# 添加可执行文件或库
# ...(省略了添加可执行文件或库的代码)# 打包ament包
ament_auto_package()

功能概述

ament_auto_package 宏执行以下主要功能:

  1. 生成必要的配置文件:为 ROS 2 包生成必要的配置文件,如 setup.pysetup.bash 等,这些文件用于在 ROS 2 环境中设置包的路径和依赖项。

  2. 安装头文件和库文件:将包中的头文件和库文件安装到 ROS 2 的安装目录中,以便其他包可以在编译时找到它们。

  3. 处理依赖项:虽然 ament_auto_find_build_dependencies() 宏用于在编译时查找依赖项,但 ament_auto_package 宏也可能涉及与依赖项相关的打包任务,如生成依赖项列表等。

  4. 生成元数据:为 ROS 2 包生成元数据,如版本信息、作者信息等,这些信息对于包的分发和使用非常重要。

注意事项

  • 确保在调用 ament_auto_package() 宏之前已经添加了所有必要的可执行文件、库和测试。
  • 如果你的包包含自定义的 CMake 宏或函数,并且这些宏或函数需要在打包过程中执行特定任务,请确保它们在 ament_auto_package() 宏之前被定义和调用。
  • ament_cmake_auto 包是 ROS 2 的一部分,因此在使用它之前,请确保你的 ROS 2 环境已经正确安装并配置了所有必要的依赖项。
    总之,ament_auto_package 宏是 ROS 2 中用于简化包打包过程的一个非常有用的工具。通过自动执行与打包相关的各种任务,它可以帮助开发者节省时间和精力,并减少因手动配置错误而导致的问题。

11 ament_auto_find_build_dependencies()的用法

ament_auto_find_build_dependencies() 是 ROS 2 中 ament_cmake 包提供的一个宏,用于在 CMakeLists.txt 文件中自动查找并包含构建依赖项。这个宏简化了依赖项查找的过程,使得开发者不需要手动为每个依赖项调用 find_package()

基本用法

在 CMakeLists.txt 文件中,ament_auto_find_build_dependencies() 宏通常位于文件的顶部或靠近顶部的位置,以便在添加任何库、可执行文件或测试之前找到并包含所有必要的依赖项。

示例

以下是一个使用 ament_auto_find_build_dependencies() 宏的 CMakeLists.txt 文件的示例片段:

cmake_minimum_required(VERSION 3.5)
project(my_ros2_package)# 查找并包含ament_cmake包
find_package(ament_cmake REQUIRED)# 自动查找构建依赖
ament_auto_find_build_dependencies()# 添加库或可执行文件
# ...(省略了添加库或可执行文件的代码)# 打包ament包
ament_package()
# 注意:在ROS 2 Foxy及更高版本中,建议使用 ament_auto_package() 替代 ament_package(),
# 但这里的重点是展示 ament_auto_find_build_dependencies() 的用法。

注意:在 ROS 2 Foxy 及更高版本中,推荐使用 ament_auto_package() 而不是 ament_package() 来打包你的包,因为 ament_auto_package() 提供了更多的自动化和简化。但是,ament_auto_find_build_dependencies() 的用法在所有支持 ROS 2 的版本中都是相似的。

功能概述

ament_auto_find_build_dependencies() 宏执行以下主要功能:

  1. 查找构建依赖项:它会自动查找并包含你的包在构建过程中所需的所有依赖项。这通常是通过读取 package.xml 文件中列出的依赖项来完成的,因为 ROS 2 使用 package.xml 文件来管理包的依赖关系。

  2. 包含依赖项:对于找到的每个依赖项,它会调用 find_package()(或等效的 CMake 命令)来包含该依赖项。这确保了你的包在编译时能够找到并使用这些依赖项提供的库、头文件等。

注意事项

  • 确保你的 package.xml 文件已经正确列出了所有必要的构建依赖项。
  • 如果你的包依赖于特定的 CMake 版本或具有特殊要求的依赖项,则可能需要手动调用 find_package() 来确保这些依赖项被正确包含。
  • 在某些情况下,你可能需要为特定的依赖项设置 CMake 变量或目标属性。这通常需要在 ament_auto_find_build_dependencies() 宏之后手动完成。

总之,ament_auto_find_build_dependencies() 宏是 ROS 2 中用于自动查找并包含构建依赖项的一个非常有用的工具。通过简化依赖项查找的过程,它可以帮助开发者节省时间和精力,并减少因手动配置错误而导致的问题。

通过上述介绍的语法和命令,你可以定义项目的构建目标、添加源文件、链接库、设置编译选项
和依赖,以及安装目标和文件。这些功能使得CMake成为ROS 2中不可或缺的构建系统。

相关文章:

ROS 2中,CMakeList.txt常见语法

在ROS 2中&#xff0c;CMakeList.txt 文件扮演着配置和管理构建过程的重要角色。这个文件遵循CMake的语法&#xff0c;用于定义如何编译和链接源代码。下面是一些在ROS 2项目CMakeList.txt文件中常见的语法和用法。 1. 基本结构和命令 cmake_minimum_required(VERSION )&…...

使用 prefetchComponents 进行组件预取

title: 使用 prefetchComponents 进行组件预取 date: 2024/8/17 updated: 2024/8/17 author: cmdragon excerpt: 摘要&#xff1a;本文介绍Nuxt.js中的prefetchComponents功能&#xff0c;用于预取组件以提高用户体验。通过在客户端后台下载和缓存组件&#xff0c;确保在用户…...

『 C++ 』IO流

文章目录 IO流概述iostream 的标准对象C流和C标准库I/O函数的同步 sync_with_stdiofstream 文件流文件流的打开标志二进制读写二进制读写的浅拷贝问题文本读写 字符串流注意 IO流概述 流是指数据的有序传输序列,路表示数据从一个地方流向另一个地方的过程,流可以是输入流也可以…...

enhanced Input Action IA_Look中Action value引脚没有分割结构体引脚的选项

UE5系列文章目录 文章目录 UE5系列文章目录前言二、使用步骤解决办法 前言 据说&#xff0c;unreal engine5中准备废弃“项目设置”中“输入”&#xff0c;操作映射&#xff0c;轴映射。取而代之的是&#xff1a; 使用增强的输入动作&#xff08;Enhanced Input Actions&#…...

C# NetworkStream、ConcurrentDictionary、Socket类、SerialPort、局域网IP 和广域网IP

一、NetworkStream 什么是NetworkStream&#xff1f; NetworkStream 是 .NET Framework 中用于在网络上进行数据传输的流类。它属于System.Net.Sockets 命名空间&#xff0c;并提供了通过网络连接进行读写操作的功能。NetworkStream 主要用于处理从网络套接字&#xff08;Soc…...

大模型--学习范式

1. 自监督学习&#xff08;Self-Supervised Learning&#xff09; 概念&#xff1a;自监督学习是一种特殊形式的监督学习&#xff0c;其中标签不是由人工标注的&#xff0c;而是从输入数据本身自动生成的。模型利用这些自动生成的标签进行训练。自监督学习通常用于预训练阶段&…...

Hadoop-yarn-unauthorized 未授权访问漏洞

一、漏洞描述&#xff1a; Hadoop是一款由Apache基金会推出的分布式系统框架&#xff0c;它通过著名的 MapReduce 算法进行分布式处理&#xff0c;Yarn是Hadoop集群的资源管理系统。YARN提供有默认开放在8088和8090的REST API&#xff08;默认前者&#xff09;允许用户直接通过…...

工作流调度系统(DolphinScheduler、Azkaban、Airflow、Oozie 和 XXL-JOB)

文章目录 1. DolphinScheduler1.1 DolphinScheduler介绍1.2 DolphinScheduler优点 2. Azkaban2.1 Azkaban介绍2.2 Azkaban优点 3. Airflow3.1 Airflow介绍3.1 Airflow优点 4. Oozie4.1 Oozie 介绍4.2 Oozie 优点 5. XXL-JOB5.1 XXL-JOB介绍5.2 XXL-JOB优点 6. 总结 1. DolphinS…...

PyTorch 基础学习(5)- 神经网络

系列文章&#xff1a; PyTorch 基础学习&#xff08;1&#xff09; - 快速入门 PyTorch 基础学习&#xff08;2&#xff09;- 张量 Tensors PyTorch 基础学习&#xff08;3&#xff09; - 张量的数学操作 PyTorch 基础学习&#xff08;4&#xff09;- 张量的类型 PyTorch 基础学…...

CI/CD 自动化:最大限度地提高极狐GitLab 群组的“部署冻结”影响

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门面向中国程序员和企业提供企业级一体化 DevOps 平台&#xff0c;用来帮助用户实现需求管理、源代码托管、CI/CD、安全合规&#xff0c;而且所有的操作都是在一个平台上进行&#xff0c;省事省心省钱。可以一键安装极狐GitL…...

单元训练10:定时器实现秒表功能-数组方式

蓝桥杯 小蜜蜂 单元训练10&#xff1a;定时器实现秒表功能-数组方式 /** Description:* Author: fdzhang* Email: zfdcqq.com* Date: 2024-08-15 21:58:53* LastEditTime: 2024-08-16 19:07:27* LastEditors: fdzhang*/#include "stc15f2k60s2.h"#define LED(x) …...

国外项目管理软件最佳实践:选型与应用

国内外主流的10款国外项目管理软件对比&#xff1a;PingCode、Worktile、Asana、Trello、Monday.com、ClickUp、Wrike、ProofHub、Zoho Projects、Hive。 在寻找适合的国外项目管理软件时&#xff0c;你是否感到不知从何选择&#xff1f;市场上琳琅满目的选项往往令人眼花缭乱&…...

Angular组件概念

Angular 是一个由 Google 维护的开源前端框架&#xff0c;用于构建单页面应用&#xff08;SPA&#xff09;和移动Web应用。Angular 应用由多个组件&#xff08;Components&#xff09;组成&#xff0c;这些组件是 Angular 应用构建块的基本单位。 1. Angular 组件的基本概念 …...

嵌入式人工智能ESP32(4-PWM呼吸灯)

1、PWM基本原理 PWM&#xff08;Pulse-width modulation&#xff09;是脉冲宽度调制的缩写。脉冲宽度调制是一种模拟信号电平数字编码方法。脉冲宽度调制PWM是通过将有效的电信号分散成离散形式从而来降低电信号所传递的平均功率的一种方式。所以根据面积等效法则&#xff0c;…...

继承 (上)【C++】

文章目录 继承的定义继承的语法继承权限和继承到子类后父类成员的访问限定符的变化继承到子类后父类成员的访问限定符的变化 子类继承到了父类的什么&#xff1f;继承中的作用域子类和父类之间的赋值转换子类对象可以直接赋值给父类对象&#xff0c;但是父类对象不能直接赋值给…...

WPF打印控件内容

当我们想打印控件内容时&#xff0c;如一个Grid中的内容&#xff0c;可以用WPF中PrintDialog类的PrintVisual()方法来实现 界面如下&#xff1a; XAML代码如下 <Grid><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition Width"300"…...

[C++][opencv]基于opencv实现photoshop算法图像剪切

【测试环境】 vs2019 opencv4.8.0 【效果演示】 【核心实现代码】 //图像剪切 //参数&#xff1a;src为源图像&#xff0c; dst为结果图像, rect为剪切区域 //返回值&#xff1a;返回0表示成功&#xff0c;否则返回错误代码 int imageCrop(InputArray src, OutputArray dst,…...

四十、大数据技术之Kafka3.x(3)

&#x1f33b;&#x1f33b; 目录 一、Kafka Broker1.1 Kafka Broker工作流程1.1.1 Zookeeper 存储的Kafka信息1.1.2 Kafka Broker 总体工作流程1.1.3 Broker 重要参数 1.2 生产经验——节点服役和退役1.2.1 服役新节点1.2.2 退役旧节点 1.3 Kafka 副本1.3.1 副本基本信息1.3.2…...

redis——基本命令

什么是Reids&#xff08;REmote Dictionary Server&#xff09; Redis是现在主流的数据库之一&#xff0c;是一个使用ANSI C编写的开源、包含多种数据结构、支持网络的、基于内存、可选持久性的键值对存储数据。 特性 1.速度快 &#xff1a;Redis的数据全部存储瑜内存中。 …...

pytorch实现单层线性回归模型

文章目录 简述代码重构要点 数学模型、运行结果数据构建与分批模型封装运行测试 简述 python使用 数值微分法 求梯度&#xff0c;实现单层线性回归-CSDN博客 python使用 计算图&#xff08;forward与backward&#xff09; 求梯度&#xff0c;实现单层线性回归-CSDN博客 数值微分…...

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行&#xff0c;YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID&#xff1a; YW3…...

Web中间件--tomcat学习

Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机&#xff0c;它可以执行Java字节码。Java虚拟机是Java平台的一部分&#xff0c;Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

基于PHP的连锁酒店管理系统

有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...

WebRTC从入门到实践 - 零基础教程

WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC&#xff1f; WebRTC&#xff08;Web Real-Time Communication&#xff09;是一个支持网页浏览器进行实时语音…...

嵌入式常见 CPU 架构

架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集&#xff0c;单周期执行&#xff1b;低功耗、CIP 独立外设&#xff1b;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel&#xff08;原始…...

沙箱虚拟化技术虚拟机容器之间的关系详解

问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西&#xff0c;但是如果把三者放在一起&#xff0c;它们之间到底什么关系&#xff1f;又有什么联系呢&#xff1f;我不是很明白&#xff01;&#xff01;&#xff01; 就比如说&#xff1a; 沙箱&#…...

从物理机到云原生:全面解析计算虚拟化技术的演进与应用

前言&#xff1a;我的虚拟化技术探索之旅 我最早接触"虚拟机"的概念是从Java开始的——JVM&#xff08;Java Virtual Machine&#xff09;让"一次编写&#xff0c;到处运行"成为可能。这个软件层面的虚拟化让我着迷&#xff0c;但直到后来接触VMware和Doc…...

WEB3全栈开发——面试专业技能点P7前端与链上集成

一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染&#xff08;SSR&#xff09;与静态网站生成&#xff08;SSG&#xff09; 框架&#xff0c;由 Vercel 开发。它简化了构建生产级 React 应用的过程&#xff0c;并内置了很多特性&#xff1a; ✅ 文件系…...