转载:vscode gcc makefile git 配置入门

VSCode+GCC+Makefile+GitHub项目管理---基础篇

             <div id="article_content" class="article_content clearfix">
        <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-211130ba7a.css">
                        <div id="content_views" class="markdown_views prism-dracula">
                <!-- flowchart 箭头图标 勿删 -->
                <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
                    <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
                </svg>
                                        <h1><a name="t0"></a><a name="t0"></a><a id="VSCode_0"></a>一、VSCode简介</h1>

Visual Studio Code (简称 VS Code / VSC) 是一款免费开源的现代化轻量级代码编辑器,支持几乎所有主流的开发语言的语法高亮、智能代码补全、自定义热键、括号匹配、代码片段、代码对比 Diff、GIT 等特性,支持插件扩展,并针对网页开发和云端应用开发做了优化。软件跨平台支持 Win、Mac 以及 Linux。教程见链接:Visual Studio Code官方教程

二、GCC环境配置

GCC 编译器是 Linux 下默认的 C/C++ 编译器,大部分 Linux 发行版中都是默认安装的,通常以 Linux 命令的形式在终端(Shell)中使用。GCC编译命令参数详见博客:GCC参数详解

Windows下如果也想使用GCC编译器(开源软件最常用的编译器之一),推荐安装MinGW,安装教程见博客:MinGW安装和使用

三、VSCode编译调试C++程序

VSCode配置C/C++环境并编译运行调试的过程在网上找到一篇不错的博客:整理VSC配置C++环境并编译运行,这里不再重复详述,只做一点补充。
下面分别贴出launch.json与tasks.json的配置项供参考:

// launch.json:

{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
“version”: “0.2.0”,
“configurations”: [
{
“name”: “C++(gdb) Launch”, //DEBUG中出现的名字
“preLaunchTask”: “cppdbg”, //在launch之前运行的任务名,要跟tasks.json中的"label"大小写一致
“type”: “cppdbg”,
“request”: “launch”,
“program”: f i l e D i r n a m e / {fileDirname}/ fileDirname/{fileBasenameNoExtension}.exe”, //需要运行的是当前打开文件的目录中,名字和当前文件相同,但扩展名为exe的程序
“args”: [],
“stopAtEntry”: false, //选为true则会在打开控制台后停滞,暂时不执行程序
“cwd”: “${workspaceFolder}”, //当前工作路径:当前文件所在的工作空间
“environment”: [],
“externalConsole”: true, //是否使用外部控制台
“MIMode”: “gdb”,
“miDebuggerPath”: “C:/MinGW/bin/gdb.exe”,
“setupCommands”: [
{
“description”: “Enable pretty-printing for gdb”,
“text”: “-enable-pretty-printing”,
“ignoreFailures”: true
}
]
}
]
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
// tasks.json:

{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
“version”: “2.0.0”,
“tasks”: [
{
“label”: “cppdbg”, //launch中"preLaunchTask"调用的任务名,需要大小写保持一致
“type”: “shell”, //任务执行的是shell命令,也可以是process程序
“command”: “g++”, //执行的命令是g++
“args”: [
“-Wall”, //生成所有警告信息
“-std=c++11”, //使用c++11标准编译
“-g”, //生成调试信息
f i l e " < / s p a n > < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > , < / s p a n > < s p a n c l a s s = " t o k e n c o m m e n t " > / / 当 前 文 件 名 < / s p a n > < s p a n c l a s s = " t o k e n s t r i n g " > " − o " < / s p a n > < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > , < / s p a n > < s p a n c l a s s = " t o k e n c o m m e n t " > / / 生 成 指 定 的 输 出 文 件 < / s p a n > < s p a n c l a s s = " t o k e n s t r i n g " > " {file}"</span><span class="token punctuation">,</span> <span class="token comment">//当前文件名</span> <span class="token string">"-o"</span><span class="token punctuation">,</span> <span class="token comment">//生成指定的输出文件</span> <span class="token string">" file"</span><spanclass="tokenpunctuation">,</span><spanclass="tokencomment">//</span><spanclass="tokenstring">"o"</span><spanclass="tokenpunctuation">,</span><spanclass="tokencomment">//</span><spanclass="tokenstring">"{fileDirname}\ f i l e B a s e n a m e N o E x t e n s i o n . e x e " < / s p a n > < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > , < / s p a n > < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > ] < / s p a n > < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > , < / s p a n > < s p a n c l a s s = " t o k e n s t r i n g " > " g r o u p " < / s p a n > < s p a n c l a s s = " t o k e n o p e r a t o r " > : < / s p a n > < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > < / s p a n > < s p a n c l a s s = " t o k e n s t r i n g " > " k i n d " < / s p a n > < s p a n c l a s s = " t o k e n o p e r a t o r " > : < / s p a n > < s p a n c l a s s = " t o k e n s t r i n g " > " b u i l d " < / s p a n > < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > , < / s p a n > < s p a n c l a s s = " t o k e n c o m m e n t " > / / 任 务 分 组 名 , 可 以 通 过 在 C o m m a n d P a l e t t e ( F 1 ) 输 入 r u n b u i l d t a s k 来 运 行 < / s p a n > < s p a n c l a s s = " t o k e n s t r i n g " > " i s D e f a u l t " < / s p a n > < s p a n c l a s s = " t o k e n o p e r a t o r " > : < / s p a n > < s p a n c l a s s = " t o k e n b o o l e a n " > t r u e < / s p a n > < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > < / s p a n > < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > , < / s p a n > < s p a n c l a s s = " t o k e n s t r i n g " > " p r o b l e m M a t c h e r " < / s p a n > < s p a n c l a s s = " t o k e n o p e r a t o r " > : < / s p a n > < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > [ < / s p a n > < s p a n c l a s s = " t o k e n s t r i n g " > " {fileBasenameNoExtension}.exe"</span><span class="token punctuation">,</span> <span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token string">"group"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token string">"kind"</span><span class="token operator">:</span> <span class="token string">"build"</span><span class="token punctuation">,</span> <span class="token comment">//任务分组名,可以通过在Command Palette(F1) 输入run build task来运行</span> <span class="token string">"isDefault"</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">"problemMatcher"</span><span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token string">" fileBasenameNoExtension.exe"</span><spanclass="tokenpunctuation">,</span><spanclass="tokenpunctuation">]</span><spanclass="tokenpunctuation">,</span><spanclass="tokenstring">"group"</span><spanclass="tokenoperator">:</span><spanclass="tokenpunctuation"></span><spanclass="tokenstring">"kind"</span><spanclass="tokenoperator">:</span><spanclass="tokenstring">"build"</span><spanclass="tokenpunctuation">,</span><spanclass="tokencomment">//,CommandPalette(F1)runbuildtask</span><spanclass="tokenstring">"isDefault"</span><spanclass="tokenoperator">:</span><spanclass="tokenboolean">true</span><spanclass="tokenpunctuation"></span><spanclass="tokenpunctuation">,</span><spanclass="tokenstring">"problemMatcher"</span><spanclass="tokenoperator">:</span><spanclass="tokenpunctuation">[</span><spanclass="tokenstring">"gcc”, // 使用gcc捕获错误
],
}
]
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

VSCode的DEBUG功能也挺方便,可以追踪监视变量及地址的变化、堆栈调用、多种断点分析等功能,比如下面给出一段案例代码,并插入一个条件断点,调试界面见下图示:

// test.cpp:

#include <cstdio>
#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
int i;
printf(“Hello,World.\n”);
for(i = 0; i < 10; i++){
cout << i << " : " << &i << endl; //添加一个i ==5 的条件断点供调试
}
getchar();
return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

Test调试界面

四、代码与GitHub同步

之前我写过一篇GitHub社会化编程的博文,养成社会化编程的习惯让自己嵌入到全球软件工程师的协作网络中,提高自己的开发效率和能力名片。VSCode原生支持Git倒是提供了不少便利,从下图Source Control(Ctrl + Shift + G)可以看到VSC原生支持的命令主要是保持本地与远程代码同步的,新建或切换工作分支、向工作分支增加新文件等操作还是需要借助Git完成,命令参考如下:

λ git init							#初始化仓库
Initialized empty Git repository in D:/VSCode/.git/

λ git checkout -b master #新建master工作分支并切换到该分支
Switched to a new branch ‘master’
#将已新建好的远程仓库添加为本地仓库的远程仓库,并将该远程仓库在本地的标识符设为test
λ git remote add test git@github.com:StreamAI/VSCode.git

λ git add --all #将默认的master工作分支内的文件添加到index暂存区

λ git status #查看仓库的状态
On branch master

No commits yet

Changes to be committed:
(use “git rm --cached <file>…” to unstage)

    new file:   .vscode/launch.json
    new file:   .vscode/tasks.json
    new file:   CPP/test.cpp
    new file:   CPP/test.exe
    new file:   README.md

λ git commit -m “Add test c++ script” #将当前暂存区内的文件实际保存到本地仓库的历史记录中
[master (root-commit) c88d983] Add test c++ script
5 files changed, 75 insertions(+)
create mode 100644 .vscode/launch.json
create mode 100644 .vscode/tasks.json
create mode 100644 CPP/test.cpp
create mode 100644 CPP/test.exe
create mode 100644 README.md

λ git push test master #将当前分支下本地仓库的内容推送给远程仓库的master分支
Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Delta compression using up to 4 threads
Compressing objects: 100% (8/8), done.
Writing objects: 100% (9/9), 19.58 KiB | 2.80 MiB/s, done.
Total 9 (delta 0), reused 0 (delta 0)
To github.com:StreamAI/VSCode.git

  • [new branch] master -> master
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

Git Sync
GitHub示例代码见链接:https://github.com/StreamAI/VSCode

五、Makefile管理项目

在软件开发中,make通常被视为一种软件构建工具。该工具主要经由读取一种名为“makefile”或“Makefile”的文件来实现软件的自动化建构。它会通过一种被称之为“target”概念来检查相关文件之间的依赖关系,这种依赖关系的检查系统非常简单,主要通过对比文件的修改时间来实现。在大多数情况下,我们主要用它来编译源代码,生成结果代码,然后把结果代码链接起来生成可执行文件或者库文件。

GCC自带make.exe工具,在MinGW中名字变成了mingw32-make.exe,如果想方便的话可以复制一个改名为make.exe,makefile的教程可参考博客:Linux基础-makefile

下面给出通过Makefile管理C/C++项目的launch.json与tasks.json配置项如下:

// launch.json:

{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
“version”: “0.2.0”,
“configurations”: [
{
“name”: “Makefile Launch(GDB)”, //DEBUG中出现的名字
“preLaunchTask”: “build”, //在launch之前运行的任务名,要跟tasks.json中的"label"大小写一致
“type”: “cppdbg”,
“request”: “launch”,
“program”: f i l e D i r n a m e / m a i n . e x e " < / s p a n > < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > , < / s p a n > < s p a n c l a s s = " t o k e n c o m m e n t " > / / 需 要 运 行 的 是 当 前 打 开 文 件 的 目 录 中 , 名 字 和 当 前 文 件 相 同 , 但 扩 展 名 为 e x e 的 程 序 < / s p a n > < s p a n c l a s s = " t o k e n s t r i n g " > " a r g s " < / s p a n > < s p a n c l a s s = " t o k e n o p e r a t o r " > : < / s p a n > < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > [ < / s p a n > < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > ] < / s p a n > < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > , < / s p a n > < s p a n c l a s s = " t o k e n s t r i n g " > " s t o p A t E n t r y " < / s p a n > < s p a n c l a s s = " t o k e n o p e r a t o r " > : < / s p a n > < s p a n c l a s s = " t o k e n b o o l e a n " > f a l s e < / s p a n > < s p a n c l a s s = " t o k e n p u n c t u a t i o n " > , < / s p a n > < s p a n c l a s s = " t o k e n c o m m e n t " > / / 选 为 t r u e 则 会 在 打 开 控 制 台 后 停 滞 , 暂 时 不 执 行 程 序 < / s p a n > < s p a n c l a s s = " t o k e n s t r i n g " > " c w d " < / s p a n > < s p a n c l a s s = " t o k e n o p e r a t o r " > : < / s p a n > < s p a n c l a s s = " t o k e n s t r i n g " > " {fileDirname}/main.exe"</span><span class="token punctuation">,</span> <span class="token comment">//需要运行的是当前打开文件的目录中,名字和当前文件相同,但扩展名为exe的程序</span> <span class="token string">"args"</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token string">"stopAtEntry"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token comment">//选为true则会在打开控制台后停滞,暂时不执行程序</span> <span class="token string">"cwd"</span><span class="token operator">:</span> <span class="token string">" fileDirname/main.exe"</span><spanclass="tokenpunctuation">,</span><spanclass="tokencomment">//exe</span><spanclass="tokenstring">"args"</span><spanclass="tokenoperator">:</span><spanclass="tokenpunctuation">[</span><spanclass="tokenpunctuation">]</span><spanclass="tokenpunctuation">,</span><spanclass="tokenstring">"stopAtEntry"</span><spanclass="tokenoperator">:</span><spanclass="tokenboolean">false</span><spanclass="tokenpunctuation">,</span><spanclass="tokencomment">//true</span><spanclass="tokenstring">"cwd"</span><spanclass="tokenoperator">:</span><spanclass="tokenstring">"{workspaceFolder}”, //当前工作路径:当前文件所在的工作空间
“environment”: [],
“externalConsole”: true, //是否使用外部控制台
“MIMode”: “gdb”,
“miDebuggerPath”: “C:\MinGW\bin\gdb.exe”,
“setupCommands”: [
{
“description”: “Enable pretty-printing for gdb”,
“text”: “-enable-pretty-printing”,
“ignoreFailures”: true
}
]
}
]
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
// tasks.json:

{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
“version”: “2.0.0”,
“tasks”: [
{
“label”: “build”, //launch中"preLaunchTask"调用的任务名,需要大小写保持一致
“type”: “shell”, //任务执行的是shell命令,也可以是process程序
“command”: “mingw32-make”, //执行的命令是mingw32-make
“args”: [
“-C”, //跳转到指定目录去读取目标目录下的Makefile文件
“./Makefile”, //要跳转的目标目录
“clean”, //要执行的任务
“default”, //要执行的下一个任务
],
“group”: {
“kind”: “build”, //任务分组名,可以通过在Command Palette(F1) 输入run build task来运行
“isDefault”: true
},
“problemMatcher”: [
“$gcc”, // 使用gcc捕获错误
],
}
]
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

下面给出C++项目的代码,示例代码比较简单,重点看Makefile代码如下:

#Makefile

#自定义变量
MAKE = mingw32-make
CC = g++
#编译选项,生成所有警告、不优化、采用c++11标准、输出调试信息、只编译并生成目标文件
CFLAGS = -Wall -O0 -std=c++11 -g -c
#wildcard为Makefile模式匹配关键字,获取目标目录符合匹配模式的所有文件名
SRCS = KaTeX parse error: Expected 'EOF', got '#' at position 98: …token comment">#̲patsubst为Makefi…(patsubst ./%.cpp, ./%.o, $(SRCS))
EXES = main.exe
RM = rm -f

#默认任务
default:
#默认任务要执行的命令,按上面的变量名替换为变量值后执行,前面必须有一个Tab符
( < / s p a n > M A K E < s p a n c l a s s = " t o k e n v a r i a b l e " > ) < / s p a n > < / s p a n > < s p a n c l a s s = " t o k e n v a r i a b l e " > < s p a n c l a s s = " t o k e n v a r i a b l e " > (</span>MAKE<span class="token variable">)</span></span> <span class="token variable"><span class="token variable"> (</span>MAKE<spanclass="tokenvariable">)</span></span><spanclass="tokenvariable"><spanclass="tokenvariable">(EXES)

#模式匹配,冒号前者为目标项,冒号后面为依赖项
( < / s p a n > E X E S < s p a n c l a s s = " t o k e n v a r i a b l e " > ) < / s p a n > < / s p a n > < s p a n c l a s s = " t o k e n k e y w o r d " > : < / s p a n > < s p a n c l a s s = " t o k e n v a r i a b l e " > < s p a n c l a s s = " t o k e n v a r i a b l e " > (</span>EXES<span class="token variable">)</span></span><span class="token keyword">:</span> <span class="token variable"><span class="token variable"> (</span>EXES<spanclass="tokenvariable">)</span></span><spanclass="tokenkeyword">:</span><spanclass="tokenvariable"><spanclass="tokenvariable">(OBJS)
# 表 示 规 则 中 所 有 的 依 赖 项 , ^表示规则中所有的依赖项, @表示规则中的目标
$(CC) − o < s p a n c l a s s = " t o k e n v a r i a b l e " > ^ -o <span class="token variable"> o<spanclass="tokenvariable">@

# %模式自动匹配符
%.o: %.cpp
# KaTeX parse error: Expected 'EOF', got '&' at position 1: &̲lt;表示规则中的第一个依赖项…(CC) $(CFLAGS) KaTeX parse error: Expected 'EOF', got '&' at position 30: …oken operator">&̲lt;</span> -o <…@

#伪目标,声明clean为伪目标或标签,为了避免该清理任务与文件名相同而被错识别
.PHONY: clean
clean:
#清理之前的目标文件,以便下次完整的重新编译
( < / s p a n > R M < s p a n c l a s s = " t o k e n v a r i a b l e " > ) < / s p a n > < / s p a n > < s p a n c l a s s = " t o k e n v a r i a b l e " > < s p a n c l a s s = " t o k e n v a r i a b l e " > (</span>RM<span class="token variable">)</span></span> <span class="token variable"><span class="token variable"> (</span>RM<spanclass="tokenvariable">)</span></span><spanclass="tokenvariable"><spanclass="tokenvariable">(OBJS) $(EXES)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
// test.cpp:

#include “test.h”
#include <cstdio>

int main(int argc, char *argv[])
{
float a = 8.7, b = 3.9;
printf("%f + %f = %f\n",a ,b, add(a,b));
printf("%f - %f = %f\n",a ,b, sub(a,b));
printf("%f * %f = %f\n",a ,b, mul(a,b));
getchar();
return 0;
}

// test.h:

#ifndef _TEST_H
#define _TEST_H

float add(float a, float b);
float sub(float a, float b);
float mul(float a, float b);

#endif

// arithmetic.cpp:

#include “test.h”

float add(float a, float b)
{
return a + b;
}

float sub(float a, float b)
{
return a - b;
}

float mul(float a, float b)
{
return a * b;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

配置文件中涉及到目录相对关系,下面给出工作空间的目录层级关系及程序执行结果,具体代码可参考GitHub:https://github.com/StreamAI/VSCode,前面调试单个源文件的配置文件.vscode挪到了VSCode\CPP目录下,如果想复现结果只需替换配置文件即可。
在这里插入图片描述

                                </div><div><div></div></div>
            <link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-60ecaf1f42.css" rel="stylesheet">
                                <div></div>
                    
        <div class="person-messagebox">
            <div class="left-message"><a href="https://blog.csdn.net/m0_37621078">
                <img src="https://profile.csdnimg.cn/2/2/4/3_m0_37621078" class="avatar_pic" username="m0_37621078">
            </a></div>
            <div class="middle-message">
                                    <div class="title"><span class="tit "><a href="https://blog.csdn.net/m0_37621078" data-report-click="{&quot;mod&quot;:&quot;popu_379&quot;,&quot;ab&quot;:&quot;new&quot;}" target="_blank">StreamAI</a></span>
                    <!-- 等级,level -->
                                            <img class="identity-icon" src="https://csdnimg.cn/identity/blog4.png">                                            </div>
                <div class="text"><span>原创文章 67</span><span>获赞 42</span><span>访问量 3万+</span></div>
            </div>
                            <div class="right-message">
                                        <a class="btn btn-sm  bt-button personal-watch" data-report-click="{&quot;mod&quot;:&quot;popu_379&quot;,&quot;ab&quot;:&quot;new&quot;}">关注</a>
                                                            <a href="https://im.csdn.net/im/main.html?userName=m0_37621078" target="_blank" class="btn btn-sm bt-button personal-letter">私信
                    </a>
                                </div>
                        </div>
                    
    </div>
</article>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值