ARM嵌入式编译器控制诊断信息(warning/error)

文章详细介绍了ARM编译器如armclang在处理警告和错误时的诊断信息格式,以及如何通过命令行选项来控制这些警告和错误的显示,包括将警告转换为错误、禁止特定警告等。此外,还提到了使用pragma在源代码中控制诊断信息的方法,以及armasm和armlink等工具的消息格式和控制选项。

ARM编译器以警告(warning)和错误(error)的形式来提供编译诊断信息,并且用户可以通过一些命令行选项,来控制这些warnings和errors的打开或者关闭。编译器会在程序编译和链接过程中将遇到的warnings和errors在控制终端打印出来,如果用户有多个源代码文件,当errors被发现时,编译器只会报告第一个源文件的诊断信息。 

目录

1 armclang诊断信息的格式

2 armclang常用的控制诊断消息的选项

3 使用示例

4 使用 pragma控制诊断信息

5 armasm 和 armlink的消息格式

6 armasm, armlink, armar, fromelf等工具控制诊断消息选项

--brief_diagnostics

--diag_error=[,]...

--diag_remark=[,]...

--diag_style=arm|ide|gnu

--diag_suppress=[,]...

--diag_warning=[,]...

--errors=

--remarks

7 参考文章


1 armclang诊断信息的格式

 armclang遇到warning或者error时,其诊断信息的格式如下

:<file>:<line>:<col>: <type>: <message>
  • <file> :出现error 或者 warning 的源文件名字
  • <line> : 出现error 或者 warning时的行号
  • <col> : 出现error 或者 warning时的列号
  • <type> : 消息类型,比如可以为:error 或者 warning
  • <message> : 具体的消息详情,该文本可能以-W<flag>形式的诊断标志结束,例如-Wvla-extension,用来标识error 或者 warning。只有可以抑制(suppress)的消息才具有关联标志。无法抑制的错误没有关联标志。

 比如下面的warning消息示例:

file.c:8:7: warning: variable length arrays are a C99 feature [-Wvla-extension]
 int i[n];
      ^

 该warning信息会告诉用户:

警告发生在file.c文件的第8行第7列开始的地方,警告是关于 i[n] 的,即在声明数组是,使用变量作为数组的长度,这个做法在当前编译器看来是个警告。在消息的最后也告诉了用户控制这个waring的flag是 vla-extension ,是因为用了[-Wvla-extension] 编译选项才打开该flag的warning信息,所以如果想要禁止此类行为产生waring消息,可以使用[-Wno-vla-extension] 选项。

2 armclang常用的控制诊断消息的选项

Common diagnostic options
OptionDescription
-Werror将所有警告转换为错误。
-Werror=<flag>将警告标志<flag>变为错误。
-Wno-error=<flag>即使指定了-Werror,也保留警告标志<flag>作为警告。
-W<flag>启用警告标志<flag>。
-Wno-<flag>禁止警告标志<flag>。
-w禁止所有警告。注意,这个选项是小写的w。
-Weverything打开所有警告。
-Wpedantic如果代码违反严格的ISO C和ISO c++,则生成警告。
-pedantic如果代码违反严格的ISO C和ISO c++,则生成警告。
-pedantic-errors如果代码违反严格的ISO C和ISO c++,则生成错误。
-f[no-]color-diagnostics该选项控制Clang是否以彩色打印诊断信息,当检测到支持彩色的终端时,默认为打开。
-f[no-]diagnostics-show-hotness在诊断行中启用配置文件热度信息(hotness)。
-f[no-]diagnostics-fixit-info启用诊断输出中的FixIt信息。这个选项(默认为on)控制Clang是否在它知道如何修复特定诊断的情况下打印信息。

3 使用示例

比如有一个file.c文件如下:

#include <stdlib.h>
#include <stdio.h>

void function (int x) {
  int i;
  int y=i+x;

/* 第三个 %d 缺少对应参数*/
  printf("Result of %d plus %d is %d\n", i, x); 
/* call这个函数在当前文件中没有被声明过,所以是隐式声明 (implicit declaration)*/
  call(); 

  return;
}

 当使用如下命令进行编译时:

armclang --target=aarch64-arm-none-eabi -march=armv8 -c file.c

 默认情况下,编译器会检查 printf() 函数声明的格式,确保 % 与传入的参数个数是否匹配,因此armclang会报如下警告信息:

file.c:9:36: warning: more '%' conversions than data arguments [-Wformat]
  printf("Result of %d plus %d is %d\n", i, x);
                                   ^

此外,在默认情况下,对 .c 文件,armclang使用 gnu11 的标准进行编译,该语言标准不支持隐式函数声明,因此会报如下警告:

file.c:11:3: warning: implicit declaration of function 'call' is invalid C99 [-Wimplicit-function-declaration]
  call();
  ^

关闭所有warning, 使用 -w:

armclang --target=aarch64-arm-none-eabi -march=armv8-a -c file.c -w

关闭 -Wformat 带来的warning, use -Wno-format:

armclang --target=aarch64-arm-none-eabi -march=armv8-a -c file.c -Wno-format

将 -Wformat 消息产生的warning作为 error报告, use -Werror=format:

armclang --target=aarch64-arm-none-eabi -march=armv8-a -c file.c -Werror=format

默认情况下,某些诊断消息被抑制。查看所有诊断消息, use -Weverything:

armclang --target=aarch64-arm-none-eabi -march=armv8-a -c file.c -Weverything

4 使用 pragma控制诊断信息

除了在armclang命令行中添加诊断消息选项,armclang还支持在源代码中添加选项,详情可以参考文档:Clang Compiler User’s Manual — Clang 17.0.0git documentationhttps://clang.llvm.org/docs/UsersManual.html#controlling-errors-and-warnings

Clang还可以通过在源代码中使用pragma来控制启用哪些诊断。这对于关闭源代码部分中的特定警告非常有用。为了与现有源代码兼容,Clang支持GCC的pragma,以及一些扩展。pragma可以控制任何可以从命令行使用的警告。警告可以设置为忽略、警告、错误或致命。下面的示例代码将告诉Clang或GCC忽略-Wall警告: 

#pragma GCC diagnostic ignored "-Wall"

#pragma clang diagnostic ignored "-W<name>"
// 忽略由<name>指定的诊断消息。

#pragma clang diagnostic warning "-W<name>"
// 将<name>指定的诊断消息设置为警告级别。

#pragma clang diagnostic error "-W<name>"
// 将<name>指定的诊断消息设置为error 级别。

#pragma clang diagnostic fatal "-W<name>"
// 将<name>指定的诊断消息设置为致命错误 fatal error 级别。

#pragma clang diagnostic push
// 保存诊断状态,以便恢复。

#pragma clang diagnostic pop
// 恢复上次保存的诊断状态。

用户也可以使用命令行选项 -W<name>来禁止或更改消息的级别,但是该更改适用于整个编译,而不是当前源文件。

关于 push 和 pop的操作,可以看如下示例:

#if foo
#endif foo /* no warning when compiling with -Wextra-tokens */

#pragma clang diagnostic push
#pragma clang diagnostic warning "-Wextra-tokens"

#if foo
#endif foo /* warning: extra tokens at end of #endif directive */

#pragma clang diagnostic pop

 当使用如下命令编译时:

armclang --target=arm-arm-none-eabi -march=armv7-a -c foo.c -o foo.o -Wno-extra-tokens

编译器只会对第二个 #endif foo 示例发出警告:

foo.c:8:8: warning: extra tokens at end of #endif directive [-Wextra-tokens]

#endif foo /* warning: extra tokens at end of #endif directive */
       ^
       //
1 warning generated.

5 armasm 和 armlink的消息格式

 armasm 和 armlink的消息格式如下:

type: prefix id suffix: message_text
  • <type>, 有以下类型选项:
    • Internal fault :  内部故障,内部故障表示工具内部出现问题。请与您的供应商联系并提供反馈。
    • Error:错误表示导致工具停止的问题。
    • Warning:警告表示异常情况可能表明存在问题,但该工具仍在继续。
    • Remark:备注,备注是常用的工具用法,但有时不符合常规。默认情况下不显示这些诊断信息。工具继续运行。
  • <prefix>, 有以下类型选项:
    • A - armasm
    • L - armlink or armar
    • Q - fromelf
  • <id>,唯一的数字消息标识符。
  • <suffix>,消息的类型:
    • E - Error
    • W - Warning
    • R - Remark
  • <message_text>,消息内容。

比如下面的armlink的错误消息:

Error: L6449E: While processing /home/scratch/a.out: I/O error writing file '/home/scratch/a.out': Permission denied

详情可以参考文档:

Arm Compiler for Embedded Errors and Warningshttps://developer.arm.com/documentation/100074/0620/Linker-Errors-and-Warnings/List-of-the-armlink-error-and-warning-messages

6 armasmarmlinkarmar, fromelf等工具控制诊断消息选项

--brief_diagnostics

armasm only。使用较短形式的诊断输出。原始的源行不显示,并且当错误消息文本太长而不能放在单行中时,错误消息文本不会被换行。

--diag_error=<tag>[,<tag>]...

将指定的诊断消息设置为“错误”。使用 --diag_error=warning 可以将所有的warning当作error.

--diag_remark=<tag>[,<tag>]...

将指定的诊断消息设置为Remark级别。

--diag_style=arm|ide|gnu

指定诊断消息的显示样式

--diag_suppress=<tag>[,<tag>]...

禁止指定的诊断信息. 使用 --diag_suppress=error 将禁止所有可以被降级的error, 或者使用 --diag_suppress=warning 可以关闭所有的warning。降低诊断消息的级别可能会阻止工具报告重要错误。Arm建议,除非用户了解对软件的影响,否则不要降低诊断的级别。

--diag_warning=<tag>[,<tag>]...

将指定的诊断消息设置为警告级别。使用--diag warning=error 将设置所有可以降级错误为警告。

--errors=<filename>

将诊断消息的输出重定向到指定文件。

--remarks

armlink only. 启用 remark 消息的显示。

7 参考文章

Arm Compiler for Embedded Errors and Warningshttps://developer.arm.com/documentation/100074/0620/Linker-Errors-and-Warnings/List-of-the-armlink-error-and-warning-messages

Controlling diagnostic messageshttps://developer.arm.com/documentation/100748/0620/Using-Common-Compiler-Options/Controlling-diagnostic-messages?lang=en Clang Compiler User’s Manual — Clang 17.0.0git documentationhttps://clang.llvm.org/docs/UsersManual.html#controlling-errors-and-warnings

“PREFIX = arm-none-eabi- CC = $(PREFIX)gcc STM32_Per_Src_Path = Libraries/STM32F10x_StdPeriph_Driver/src SOURCES = User/main.c SOURCES += User/stm32f10x_it.c #SOURCES += Libraries/CMSIS/core_cm3.c SOURCES += Libraries/CMSIS/system_stm32f10x.c SOURCES += $(STM32_Per_Src_Path)/misc.c SOURCES += $(STM32_Per_Src_Path)/stm32f10x_rcc.c SOURCES += $(STM32_Per_Src_Path)/stm32f10x_gpio.c ASM_SOURCES = Libraries/CMSIS/start.S OBJS = $(SOURCES:.c=.o) $(ASM_SOURCES:.S=.o) TARGET = build/stm32f103_project MCU=cortex-m3 CFLAGS = -mcpu=$(MCU) -mthumb CFLAGS += -Wall -Wextra -Wpedantic #CFLAGS += -Wmissing-prototypes -Wstrict-prototypes CFLAGS += -DSTM32F10X_MD CFLAGS += -DUSE_STDPERIPH_DRIVER #CFLAGS += --specs=nano.specs CFLAGS += --specs=nosys.specs INCLUDE = -IUser INCLUDE += -ILibraries\STM32F10x_StdPeriph_Driver\inc INCLUDE += -ILibraries\CMSIS INCLUDE += -Iinterrupt INCLUDE += -IAPP LDSCRIPT = STM32F103C8_FLASH.ld LDFLAGS = -mcpu=$(MCU) -mthumb #LDFLAGS += --specs=nano.specs LDFLAGS += --specs=nosys.specs LDFLAGS += -T$(LDSCRIPT) -Wl,--gc-sections LDFLAGS += -Wl,--print-memory-usage LDFLAGS += -Wl,-Map=Build/project.map all : $(TARGET).elf $(TARGET).bin $(TARGET).hex $(TARGET).elf: $(OBJS) @echo Linking... $(CC) $(LDFLAGS) -o $@ $^ @echo Size info: $(SIZE) $@ %.o: %.c @echo Compiling $<... $(CC) $(CFLAGS) $(INCLUDE) -c -o $@ $< %.o: %.s @echo Assembling $<... $(CC) $(CFLAGS) -c -o $@ $< $(TARGET).bin: $(TARGET).elf $(OBJCOPY) -O binary $< $@ $(TARGET).hex: $(TARGET).elf $(OBJCOPY) -O ihex $< $@ clean: rm -rf Build find . -name "*.o" -type f -delete find . -name "*.d" -type f -delete flash: $(TARGET).elf openocd -f interface/stlink.cfg -f target/stm32f1x.cfg \ -c "program $< verify reset exit" clean: -del /q $(subst /,\,$(OBJS)) 2>nul -del /q $(TARGET).elf $(TARGET).bin $(TARGET).hex $(TARGET).map 2>nul flash: $(TARGET).elf openocd -f interface/stlink.cfg -f target/stm32f1x.cfg -c "program $< verify reset exit" .PHONY: all clean flash”“PS C:\Users\13336\Desktop\test\vscode_stm32\model_02> mingw32-make all makefile:87: warning: overriding recipe for target 'flash' makefile:79: warning: ignoring old recipe for target 'flash' Compiling User/main.c... arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -Wall -Wextra -Wpedantic -DSTM32F10X_MD -DUSE_STDPERIPH_DRIVER --specs=nosys.specs -IUser -ILibraries\STM32F10x_StdPeriph_Driver\inc -ILibraries\CMSIS -Iinterrupt -IAPP -c -o User/main.o User/main.c Linking... arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb --specs=nosys.specs -TSTM32F103C8_FLASH.ld -Wl,--gc-sections -Wl,--print-memory-usage -Wl,-Map=Build/project.map -o build/stm32f103_project.elf User/main.o User/stm32f10x_it.o Libraries/CMSIS/system_stm32f10x.o Libraries/STM32F10x_StdPeriph_Driver/src/misc.o Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_rcc.o Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_gpio.o Libraries/CMSIS/start.o C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/bin/ld.exe: C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/lib/thumb/v7-m/nofp\libc.a(libc_a-closer.o): in function `_close_r': closer.c:(.text._close_r+0xc): warning: _close is not implemented and will always fail C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/bin/ld.exe: C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/lib/thumb/v7-m/nofp\libc.a(libc_a-closer.o): note: the message above does not take linker garbage collection into account C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/bin/ld.exe: C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/lib/thumb/v7-m/nofp\libc.a(libc_a-lseekr.o): in function `_lseek_r': lseekr.c:(.text._lseek_r+0x14): warning: _lseek is not implemented and will always fail C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/bin/ld.exe: C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/lib/thumb/v7-m/nofp\libc.a(libc_a-lseekr.o): note: the message above does not take linker garbage collection into account C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/bin/ld.exe: C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/lib/thumb/v7-m/nofp\libc.a(libc_a-readr.o): in function `_read_r': readr.c:(.text._read_r+0x14): warning: _read is not implemented and will always fail C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/bin/ld.exe: C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/lib/thumb/v7-m/nofp\libc.a(libc_a-readr.o): note: the message above does not take linker garbage collection into account C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/bin/ld.exe: C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/lib/thumb/v7-m/nofp\libc.a(libc_a-writer.o): in function `_write_r': writer.c:(.text._write_r+0x14): warning: _write is not implemented and will always fail C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/bin/ld.exe: C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/lib/thumb/v7-m/nofp\libc.a(libc_a-writer.o): note: the message above does not take linker garbage collection into account C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/bin/ld.exe: warning: build/stm32f103_project.elf has a LOAD segment with RWX permissions C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/bin/ld.exe: User/main.o: in function `main': main.c:(.text+0x4): undefined reference to `SetSysClock' C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/bin/ld.exe: (SetSysClock): Unknown destination type (ARM/Thumb) in User/main.o main.c:(.text+0x4): dangerous relocation: unsupported relocation C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/bin/ld.exe: main.c:(.text+0x8): undefined reference to `LED_Init' C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/bin/ld.exe: (LED_Init): Unknown destination type (ARM/Thumb) in User/main.o main.c:(.text+0x8): dangerous relocation: unsupported relocation C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/bin/ld.exe: main.c:(.text+0xc): undefined reference to `LED_On' C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/bin/ld.exe: (LED_On): Unknown destination type (ARM/Thumb) in User/main.o main.c:(.text+0xc): dangerous relocation: unsupported relocation C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/bin/ld.exe: main.c:(.text+0x14): undefined reference to `Delay_ms' C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/bin/ld.exe: (Delay_ms): Unknown destination type (ARM/Thumb) in User/main.o main.c:(.text+0x14): dangerous relocation: unsupported relocation C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/bin/ld.exe: main.c:(.text+0x18): undefined reference to `LED_Off' C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/bin/ld.exe: (LED_Off): Unknown destination type (ARM/Thumb) in User/main.o main.c:(.text+0x18): dangerous relocation: unsupported relocation C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/bin/ld.exe: main.c:(.text+0x20): undefined reference to `Delay_ms' C:/Users/13336/Desktop/test/arm-gnu-toolchain-14.3.rel1-mingw-w64-i686-arm-none-eabi/bin/../lib/gcc/arm-none-eabi/14.3.1/../../../../arm-none-eabi/bin/ld.exe: (Delay_ms): Unknown destination type (ARM/Thumb) in User/main.o main.c:(.text+0x20): dangerous relocation: unsupported relocation Memory region Used Size Region Size %age Used FLASH: 1540 B 64 KB 2.35% RAM: 1984 B 20 KB 9.69% collect2.exe: error: ld returned 1 exit status mingw32-make: *** [makefile:55: build/stm32f103_project.elf] Error 1 PS C:\Users\13336\Desktop\test\vscode_stm32\model_02>”这报错是什么问题
最新发布
09-29
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SOC罗三炮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值