Qt 工程

资源

Qt Help Creating Project Files
QT5 编程入门
Qt Creator快速入门 第2版 2.4.2
Qt 工程文件(.pro)
qt creator源码全方面分析(3-1)

工程文件

Qt 帮助文档介绍:
1

示例:

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = Label
TEMPLATE = app

SOURCES += main.cpp\
        src/test/tst.cpp \
        src/widget.cpp

HEADERS  += src/widget.h \
    src/test/tst.h

FORMS    += src/widget.ui

关于 QT += core gui
2

在打开一个项目文件后会自动生成一个 .pro.user 的文件,该文件和工程文件在一个目录,用途如下:


3

项目文件

Qt Creator快速入门 第2版 2.4

项目模式设置:
在这里插入图片描述

.pro.user文件:
1# Makefile

Makefile

百度介绍:
4
5
6

QMake

Qt高级——QMake用户指南
Qt 帮助文档 qmake Manual

Qt 帮助文档介绍:
7

qmake 根据工程文件生成 makefile 文件。

添加模块

添加 widgets 模块

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

QT5 编程入门 2.1.3

书中介绍:
8

添加与特定平台有关的文件

win32 {
      SOURCES += hellowin.cpp
}
unix {
      SOURCES += hellounix.cpp
}

文件不存在时停止 qmake

!exists( main.cpp ) {
      error( "No main.cpp file found" )
}

控制台输出调试信息

win32 {
      debug {
          CONFIG += console
      }
}

变量 Variables

9

MY_VAR1 = 1
MY_VAR2 = $$MY_VAR1
MY_VAR3 = $${MY_VAR1}
TARGET = APP_$${MY_VAR1}

message(MY_VAR1: $$MY_VAR1)
message(MY_VAR2: $$MY_VAR2)
message(MY_VAR3: $$MY_VAR3)
message(TARGET: $$TARGET)

执行 qmake 后在编译输出中可以看见打印信息:

Project MESSAGE: MY_VAR1: 1
Project MESSAGE: MY_VAR2: 1
Project MESSAGE: MY_VAR3: 1
Project MESSAGE: TARGET: APP_1

CONFIG

Specifies project configuration and compiler options.
The values are recognized internally by qmake and have special meaning.

即使不特意赋值,该变量也有初始值。
如果在 debug 模式构建,qmake 工具会添加 CONFIG +=debugCONFIG += qml_debug
如果在 release 模式,qmake 工具会添加 CONFIG+=qtquickcompiler

message(config value: $$CONFIG)

CONFIG(debug, debug|release) {
    message(debug mode)
}
else {
    message(release mode)
}

debug 模式结果:

Project MESSAGE: config value: lex yacc debug exceptions depend_includepath 
testcase_targets import_plugins import_qpa_plugin windows file_copies 
qmake_use qt warn_on release link_prl flat debug_and_release 
debug_and_release_target precompile_header autogen_precompile_source 
embed_manifest_dll embed_manifest_exe shared shared release 
no_plugin_manifest win32 msvc copy_dir_files 
c++11 debug qml_debug

默认的初始值有 debug_and_release 标志,因此工程文件会执行三次,生成三个 Makefile 文件:
2


如果去掉 release 标志,但保留 debug_and_release,仍会执行三次,生成三个 Makefile 文件,但三次只会进入 **line 1,line 2 和 line 5,不会进入 line 3

CONFIG += debug
CONFIG -= release
CONFIG -= Release
CONFIG -= debug_and_release_target

message(line 1: config value: $$CONFIG)

CONFIG(debug){
    message(line 2: only debug param)
}

CONFIG(release){
    message(line 3: only release param)
}

CONFIG(debug, release|debug_and_release){
    message(line 4: test param 2)
}

CONFIG(debug, debug|release) {
    message(line 5: debug mode)
}
else {
    message(line 6: release mode)
}

Makefile 文件如下:
makefile


如果去掉 debug_and_release 标志,则工程文件只执行一次。

CONFIG -= debug_and_release
message(line 1: config value: $$CONFIG)

CONFIG(debug){
    message(line 2: only debug param)
}

CONFIG(release){
    message(line 3: only release param)
}

CONFIG(debug, release|debug_and_release){
    message(line 4: test param 2)
}

CONFIG(debug, debug|release) {
    message(line 5: debug mode)
}
else {
    message(line 6: release mode)
}

debug 模式下,执行 line 1,line 2,line 3 和 line 5,只执行一次。
Makefile 只有一个:
makefile

在 release 模式执行,则执行 line 1,line 2,line 3 和 line 6,只执行一次。

HEADERS SOURCES FORMS

添加头文件,源文件和 ui 文件;如果文件在子目录中,要将子目录写上。

假设工程的目录结果如下:
pro

HEADERS  += src/widget.h \
            src/test/tst.h

SOURCES += main.cpp\
        src/test/tst.cpp \
        src/widget.cpp

FORMS    += src/widget.ui

如果写成如下形式:

HEADERS  += widget.h \
            tst.h

SOURCES += main.cpp\
           tst.cpp\
           widget.cpp

FORMS    += widget.ui

则 Qt 的项目目录中显示如下:
pro

找不到子目录中的文件,构建出错。

INCLUDEPATH

Specifies the #include directories which should be searched when compiling the project.
To specify a path containing spaces, quote the path using the technique described in Whitespace.

定义编译器查找文件的路径,有子目录的要将所有子目录列上,否则包含头文件时要将父目录都列上。

如:工程 QLabel.pro 所在的目录为 H:\test\qt\QLabel,该目录包含如下文件:

1

src 目录如下:
2test 目录如下:
3

如果工程文件中不包含任何目录,则在 main.cpp 中要包含头文件必须加上路径

#include "src/widget.h"
#include "src/test/tst.h"

不能直接写:

//提示找不到文件
#include "widget.h"
#include "tst.h" 

如果在工程文件中添加路径:

INCLUDEPATH += src \
               src/test

main.cpp 中可直接添加头文件而不用写前面的父目录的路径。
这里包含 src 目录时并比包含其子目录,子目录 test 子目录需单独添加。

TARGET

Specifies the name of the target file. Contains the base name of the project file by default.
The project file above would produce an executable named myapp on unix and myapp.exe on Windows.

TARGET = myapp

目标文件的名字,如果目标文件是 exe 文件,则生成的文件为 myapp.exe

TEMPLATE

为工程创建模板:
3

TEMPLATE = app windows 系统则将生成 .exe 文件。

SUBDIRS

模板是 subdirs 时使用,添加子目录。
34

相关介绍:Qt包含工程集subdirs的使用

示例:

TEMPLATE = subdirs

SUBDIRS += Plugin\
           myapp

myapp.depends = Plugin/lib

myapp 工程中为:TEMPLATE = app
Plugin 工程中包含几个插件,该工程模板也是 subdirs,如下:

TEMPLATE = subdirs

SUBDIRS += lib1\
           lib2\
           lib3\
           lib4

lib1 是一个设计器插件,工程如下:

CONFIG      += plugin
TEMPLATE    = lib

Plugin 文件夹中是用到的一些插件,myapp 工程生成一个 myapp.exe 的程序。

PRE_TARGETDEPS

添加预编译头文件

预编译头文件介绍:

预编译头文件
C++预编译头文件

预编译头文件必须所有的源文件都包含。

如:

PRECOMPILED_HEADER = comm.h

DESTDIR

Specifies where to put the target file
The list of supported characters can depend on the used build tool. In particular, parentheses do not work with make.

设置目标文件存放的位置(如果模板时 APP,则是 .exe 可执行文件的位置),假如构建目录为:
H:\test\qt\build-QLabel-Desktop_Qt_5_14_2_MSVC2017_32bit-Debug
Debug模式,默认可执行文件在构建目录的子目录的debug文件夹中,如果做如下设置:

DESTDIR += bin

则可执行文件在构建目录中建立一个bin文件夹(和 debug 文件在同一目录),可执行文件在bin目录中。

如果修改可执行文件目录如下:

DESTDIR += ../label

则可执行目录在 H:\test\qt\label 目录中,其中 label 为新建的文件夹,../表示取构建目录的上级目录,即 H:\test\qt

因此,如果路径不指定绝对路径,而用相对路径,则相对构建目录的路径。

PWD

Specifies the full path leading to the directory containing the current file being parsed.
This can be useful to refer to files within the source tree when writing project files to support shadow builds.
Note: Do not attempt to overwrite the value of this variable.

当前工程文件所在的路径。
如:工程 QLabel.pro 所在的目录为 H:\test\qt\QLabel, 则打印该变量的值:

message(PWD: $$PWD)

编译输出:

Project MESSAGE: PWD: H:/test/qt/QLabel

OUT_PWD

Specifies the full path leading to the directory where qmake places the generated Makefile.
Note: Do not attempt to overwrite the value of this variable.

makefile文件存放的路径,默认在构建目录下。
如:工程 QLabel.pro 所在的目录为 H:\test\qt\QLabel, 则打印该变量的值:

message(OUT_PWD: $$OUT_PWD)

编译输出:

Project MESSAGE: OUT_PWD: H:/test/qt/build-QLabel-Desktop_Qt_5_14_2_MSVC2017_32bit-Debug

注意路径中的分隔符为 Qt 的分隔符,不是 windows 分隔符,如果要转换为 Windows 系统的分隔符,如下:

#system_path(path) 将路径中的分隔符转换为系统的分隔符
makefilePath = $$system_path($$OUT_PWD)
message(OUT_PWD: $$OUT_PWD)
message(makefilePath: $$makefilePath)

编译输出:

Project MESSAGE: OUT_PWD: H:/test/qt/build-QLabel-Desktop_Qt_5_14_2_MSVC2017_32bit-Debug
Project MESSAGE: makefilePath: H:\test\qt\build-QLabel-Desktop_Qt_5_14_2_MSVC2017_32bit-Debug

QMAKE_CFLAGS_DEBUG

Specifies the C compiler flags for debug builds. The value of this variable is typically handled by qmake or qmake.conf and rarely needs to be modified.

Qt在pro中设置运行时库MT、MTd、MD、MDd

QMAKE_CFLAGS_DEBUG += -MDd

产品名称 QMAKE_TARGET_PRODUCT

Windows only. Specifies the product for the project target; this is used where applicable for putting the product in the application’s properties.

This is only utilized if the VERSION or RC_ICONS variable is set and the RC_FILE and RES_FILE variables are not set.

版本号 VERSION

1

VERSION_PE_HEADER

2

版权声明 QMAKE_TARGET_COPYRIGHT

Windows only. Specifies the copyright information for the project target;
this is used where applicable for putting the copyright information in the application’s properties.
This is only utilized if the VERSION or RC_ICONS variable is set and the RC_FILE and RES_FILE variables are not set.

描述信息 QMAKE_TARGET_DESCRIPTION

Windows only. Specifies the description for the project target;
this is used where applicable for putting the description in the application’s properties.
This is only utilized if the VERSION or RC_ICONS variable is set and the RC_FILE and RES_FILE variables are not set.

公司名称 QMAKE_TARGET_COMPANY

Windows only. Specifies the company for the project target;
this is used where applicable for putting the company in the application’s properties.
This is only utilized if the VERSION or RC_ICONS variable is set and the RC_FILE and RES_FILE variables are not set.

应用程序的图标 RC_ICONS

Windows only. Specifies the icons that should be included into a generated .rc file.
this is used where applicable for putting the company in the application’s properties.
This is only utilized if the RC_FILE and RES_FILE variable are not set.

资源文件 RC_FILE

Windows only. Specifies the name of the Windows resource file (.rc) for the target. See Adding Windows Resource Files.

Qt 资源文件

qmake 属性

内置属性

1

自定义属性

qmake -set PROPERTY VALUE

获取属性

  1. 在命令行窗口输入命令
    1
  2. 在工程文件中获取属性,用 $$[]
message(Qt version: $$[QT_VERSION])

操作符 Operators

赋值符号 =

The = operator assigns a value to a variable:

  TARGET = myapp

The above line sets the TARGET variable to myapp. This will overwrite any values previously set for TARGET with myapp.

Appending Values +=

The += operator appends a new value to the list of values in a variable

CONFIG += console
CONFIG += release
CONFIG += debug

Removing Values -=

The -= operator removes a value from the list of values in a variable

CONFIG -= release
CONFIG -= Release
CONFIG -= debug_and_release
CONFIG -= debug_and_release_target

Adding Unique Values *=

The *= operator adds a value to the list of values in a variable, but only if it is not already present.

这个可以防止一个值被添加多次。

DEFINES *= USE_MY_STUFF

Replacing Values ~=

The ~= operator replaces any values that match a regular expression with the specified value.

DEFINES ~= s/QT_[DT].+/QT

获取变量内容 $$

TARGET = Label
TAR = $$TARGET
message(TAR: $$TAR)

帮助文档介绍 $$() 以及 $(),没明白这三个区别?

获取 qmake 属性 $$[]

The special $$[…] operator can be used to access qmake properties

  message(Qt version: $$[QT_VERSION])
  message(Qt is installed in $$[QT_INSTALL_PREFIX])
  message(Qt resources can be found in the following locations:)
  message(Documentation: $$[QT_INSTALL_DOCS])
  message(Header files: $$[QT_INSTALL_HEADERS])
  message(Libraries: $$[QT_INSTALL_LIBS])
  message(Binary files (executables): $$[QT_INSTALL_BINS])
  message(Plugins: $$[QT_INSTALL_PLUGINS])
  message(Data files: $$[QT_INSTALL_DATA])
  message(Translation files: $$[QT_INSTALL_TRANSLATIONS])
  message(Settings: $$[QT_INSTALL_CONFIGURATION])
  message(Examples: $$[QT_INSTALL_EXAMPLES])

Scopes

Scopes 和 if 语句类似。

<condition> {
      <command or definition>
      ...
  }

注意:opening brace 必须和条件语句在相同行。

示例:

CONFIG(debug) {
    message(line 2: only debug param)
}

win32 {
      SOURCES += paintwidget_win.cpp
}

!win32 {
      SOURCES -= paintwidget_win.cpp
}
嵌套
build_pass {
	 CONFIG(debug, debug|release) {
     message(line 5: debug mode)
     }
}

上述写法可以用写成如下形式:

build_pass:CONFIG(debug, debug|release) {
     message(line 5: debug mode)
}
: 操作符

You may also use the : operator to perform single line conditional assignments:

win32:DEFINES += USE_MY_STUFF
| 操作符

可以在条件语句中用 | 充当逻辑或,联合多个条件,只需要满足一个条件即可:

win32|macx {
      HEADERS += debugging.h
  }
if
if(win32|macos):CONFIG(debug, debug|release) {
      # Do something on Windows and macOS,
      # but only for the debug configuration.
  }
  win32|if(macos:CONFIG(debug, debug|release)) {
      # Do something on Windows (regardless of debug or release)
      # and on macOS (only for debug).
  }

Replace Functions

Qt 5.14 qmake Manual Replace Functions

1

absolute_path(path[,base])

Returns the absolute path of path.
If base is not specified, uses the current directory as the base directory. If it is a relative path, it is resolved relative to the current directory before use.

the following call returns the string “/home/johndoe/myproject/readme.txt”

message($$absolute_path("readme.txt", "/home/johndoe/myproject"))

basename(variablename)

Returns the basename of the file specified in variablename.

message(PWD: $$PWD)
message(PWD BaseName: $$basename(PWD))

输出:

Project MESSAGE: PWD: H:/test/qt/QLabel
Project MESSAGE: PWD BaseName: QLabel

cat(filename[,mode])

Returns the contents of filename. You can specify the following options for mode:
blob returns the entire contents of the file as one value
lines returns each line as a separate value (without line endings)
true (default value) and false return file contents as separate values, split according to qmake value list splitting rules (as in variable assignmengs).
If mode is false, values that contain only a newline character are inserted into the list to indicate where line breaks were in the file.

clean_path(path)

Returns path with directory separators normalized (converted to “/”) and redundaant ones removed, and “.” and "…"s resolved (as far as possiible). This function is a wrapper around QDir::cleanPath.

将路径分隔符转换为 Qt 的路径分隔符 /

dirname(file)

Returns the direcotry name part of the specified file.

message(PWD: $$PWD)
message(PWD DirName: $$dirname(PWD))

输出:

Project MESSAGE: PWD: H:/test/qt/QLabel
Project MESSAGE: PWD DirName: H:/test/qt

enumerate_vars

Returns a list of all defined variable names.

getenv(variablename)

Returns the value of the environment variale variablename.
This is mostly equivalent to the $$(variablename) syntax.
The getenv function, however, supports environment variables with parentheses in their name.

join(variablename, gllue, before, after)

Joins the value of variablename with glue.
If this value is not empty, this function prefixes the value with before and suffixes it with after.
variablename is the only required field, the others default to empty strings.
If you need to encode spaces in glue, before, or after, you must quote them

last(variablename)

Returns the last value of variablename.

CONTACT = firstname middlename surname phone
message($$last(CONTACT)) # phone

list(arg1 [,arg2 …, argn])

Takes an arbitrary number of arguments. It creates a uniquely named variable that contains a list of the arguments,
and returns the name of that variable. You can use the variable to write a loop as illustrated by the following code snippet

for(var, $$list(foo bar baz)) {
      ...
}

# instead of

values = foo bar baz
for(var, values) {
  ...
}

lower(arg1 [,arg2 …, argn])

Takes an arbitary numner of arguments and converts them to lower case.

quate(string)

Converts a whole string into a single entity and returns the result.

relative_path(filePath[, base])

Returns the path to filepath relative to base.
If base is not specified, it is the current project directory.
If it is relative, it is resolved relative to the current project directory before use.
If filePath is relative, it is first resolved against the base directory; in that case, this function effectively acts as $$clean_path().

replace(string, old_string, new_sring)

Replaces each instance of old_string with new_string in the contents of variable supplied as string.

MESSAGE = This is a tent.
message($$replace(MESSAGE, tent, test)) #This is a test.

shadowed(path)

Maps the path from the project source directory to the build directory.
This function returns path for in-source builds. It returns an empty string if path points outside of the source tree.

system_path(path)

Converts all directory separators within path to separators that are compatible with the shell that is used by the system() functions to invoke commands.
For example, slashes are converted to backslashes for the Windows shell.

将 Qt 的分隔符转换为系统的分隔符,如 windows 为 \

makefilePath = $$system_path($$OUT_PWD)
message(OUT_PWD: $$OUT_PWD)
message(makefilePath: $$makefilePath)

输出:

Project MESSAGE: OUT_PWD: H:/test/qt/build-QLabel-Desktop_Qt_5_14_2_MSVC2017_32bit-Debug
Project MESSAGE: makefilePath: H:\test\qt\build-QLabel-Desktop_Qt_5_14_2_MSVC2017_32bit-Debug

take_first(variablename)

Returns the first value of variablename and removes it from the source variable.

take_last(variablename)

Returns the last value of variablename and removes it from the source variable.

unique(variablename)

Returns the list of values in variablename with duplicate entries removed.

Test Functions

CONFIG(config)

QMake CONFIG() function and ‘active configuration’

2

CONFIG() 函数两个参数的语法含义:第二个参数列举了一系列的参考值,第一个参数指定第二个参数显示的系列值中的有效值。

CONFIG() 函数参数只有一个时,只要 CONFIG 变量中包含该参数,就能进入该条件语句中。

CONFIG() 函数参数有两个时,第一个参数指定 active config,即 CONFIG 变量中最后一个值第二个参数列出备选的参数值

下面示例均在 debug 模式执行。

示例:

CONFIG += release
CONFIG += debug

message(line 1: config value: $$CONFIG)

CONFIG(debug){
    message(line 2: only debug param)
}

CONFIG(release){
    message(line 3: only release param)
}

CONFIG(debug, release|debug_and_release){
    message(line 4: test param 2)
}

CONFIG(debug, debug|release) {
    message(line 5: debug mode)
}
else {
    message(line 6: release mode)
}

编译输出如下:

Project MESSAGE: line 1: config value: lex yacc debug exceptions 
depend_includepath testcase_targets import_plugins 
import_qpa_plugin windows file_copies qmake_use qt warn_on 
release link_prl flat debug_and_release debug_and_release_target 
precompile_header autogen_precompile_source 
embed_manifest_dll embed_manifest_exe shared shared 
release no_plugin_manifest win32 msvc copy_dir_files 
c++11 debug qml_debug release debug

Project MESSAGE: line 2: only debug param
Project MESSAGE: line 3: only release param
Project MESSAGE: line 5: debug mode

//重复上述内容三次

如果只想要消息执行一次,可以用 build_pass变量,该变量初始为 false,第2次和第三次执行工程文件时为 true

示例:

CONFIG += release
CONFIG += debug

message(line 1: config value: $$CONFIG)

CONFIG(debug){
    message(line 2: only debug param)
}

CONFIG(release){
    message(line 3: only release param)
}

CONFIG(debug, release|debug_and_release){
    message(line 4: test param 2)
}

!build_pass:CONFIG(debug, debug|release) {
    message(line 5: debug mode)
}
else:!build_pass {
    message(line 6: release mode)
}

结果和上个示例相同,处理 line5 只执行一次,后面两次不执行。


总结:

  1. 如果第一个参数不在二个参数的列表中,则不能进入该条件,如上述的 line 4 语句未执行。

  2. 如果第一个参数不是active config,同样不能进入该条件,如上述line 6: release mode条件不能进入。

  3. 第二个参数的备选参数列表中如果某个参数不存在也没关系,见下面示例。

CONFIG += release
CONFIG += debug

message(line 1: config value: $$CONFIG)

CONFIG(debug){
    message(line 2: only debug param)
}

CONFIG(release){
    message(line 3: only release param)
}

CONFIG(debug, release|debug_and_release){
    message(line 4: test param 2)
}

CONFIG -= release
CONFIG -= Release
message(new config value: $$CONFIG)

build_pass:CONFIG(debug, debug|release) {
    message(line 5: debug mode)
}
else:build_pass {
    message(line 6: release mode)
}

新的 CONFIG 中没有 relase ,但 line5 仍可以执行。

error(string)

This function never returns a value.
qmake displays string as an error message to the user and exits. This function should only be used for unrecoverable errors.

error(An error has occurred in the configuration process.)

include(filename)

Includes the contents of the file specified by filename into the current project at the point where it is included.
This function succeeds if filename is included; otherwise it fails. The included file is processed immediately.
You can check whether the file was included by using this function as the condition for a scope.

include( shared.pri )
OPTIONS = standard custom
!include( options.pri ) {
  message( "No custom build options specified" )
OPTIONS -= custom
}

load(feature)

Loads the feature file (.prf) specified by feature, unless the feature has already been loaded.

log(message)

Prints a message on the console. Unlike the message function, neither prepends text nor appends a line break.

message(string)

Always succeeds, and displays string as a general message to the user.
Unlike the error() function, this function allows processing to continue.

message("This is  a  message")

The above line causes “This is a message” to be written to the console. The use of quotation marks is optional, but recommended.

Note: By default, messages are written out for each Makefile generated by qmake for a given project.
If you want to ensure that messages only appear once for each project,
test the build_pass variable in conjunction with a scope to filter out messages during builds.

因为会生成几个 makefile 文件,因此 message的内容会出现几次,可以使其只出现一次:

!build_pass:message( "This is a message" )

mkpath(dirPath)

Creates the directory path dirPath. This function is a wrapper around the QDir::mkpath function

requires(condition)

Evaluates condition. If the condition is false, qmake skips this project (and its SUBDIRS) when building.
You can also use the REQUIRES variable for this purpose. However, we recommend using this function, instead.

不是有 if() 条件判断?

system(command)

Executes the given command in a secondary shell.
Succeeds if the command returns with a zero exit status; otherwise fails.
You can check the return value of this function using a scope.

system("ls /bin"): HAS_BIN = TRUE

touch(filename, reference_filename)

Updates the time stamp of filename to match the time stamp of reference_filename.

unset(variablename)

Removes variablename frrom the ccurrent context

warning(string)

Always succeeds, and display string as a wraning message to ths user.

write_file(filename, [variablename. [mode]])

Writes the values of variablename to a file with the name filename, each value on a separate line.
If variablename is not specified, creates an empty file. If mode is append and the file already exitsts, appends to it instead of replacing it.

以管理员权限运行

工程文件中增加:

QMAKE_LFLAGS += /MANIFESTUAC:\"level=\'requireAdministrator\' uiAccess=\'false\'\"

显示控制台窗口

工程文件中增加让 debug 模式时显示控制台窗口:

win32:debug {
          CONFIG += console
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值