RISC-V GCC GUI

使用说明

安装

  • 选择安装位置,默认安装于C:\Program Files\RiscvCompiler

image-20250808110732132

  • 选择快捷方式存放位置,安装预计用时1分钟

image-20250808110911551

使用

image-20250808111335704

  • 指定项目目录:C语言主程序、启动文件、链接脚本
  • 指定主程序文件名(不带文件类型后缀),指定链接脚本
  • GCC编译文件自动存入指定项目目录
image-20250808110227069

PS脚本

工具链变量

1
2
3
4
5
# TOOLCHAIN
$TOOLCHAIN_DIR = "C:\riscv\xpack-riscv-none-elf-gcc-14.2.0-3\bin"
$RISCV_GCC = "$TOOLCHAIN_DIR\riscv-none-elf-gcc.exe"
$OBJCOPY = "$TOOLCHAIN_DIR\riscv-none-elf-objcopy.exe"
$OBJDUMP = "$TOOLCHAIN_DIR\riscv-none-elf-objdump.exe"
  • gcc:RISC-V架构的交叉编译器前端
    • 将C/C++源代码编译为RISC-V目标平台的机器码
    • 管理整个编译流程(预处理→编译→汇编→链接)
    • 支持RISC-V RV32/RV64指令集及扩展(如M/C/F/D等)
  • objcopy:目标文件格式转换工具
    • 提取/转换ELF文件中的特定段(如从.elf提取.bin固件)
    • 生成可烧录的二进制镜像(如用于Flash编程)
    • 修改文件头信息或段属性
  • objdump:目标文件分析诊断工具
    • 反汇编机器码为RISC-V汇编指令
    • 显示ELF文件结构(段头、符号表等)
    • 生成带地址的汇编列表文件

文件变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# PROJECT
$PROJECT_DIR = "your_project_path"
$MAIN_CODE = "main_file_name_without_extension"

# SOURCE
$LINKER_SCRIPT = "$PROJECT_DIR\sections.lds"
$SOURCE_FILES = @(
"$PROJECT_DIR\start.S",
"$PROJECT_DIR\$MAIN_CODE.c"
)

# OUTPUT
$MAP_FILE = "$PROJECT_DIR\sys.map"
$ELF_OUTPUT = "$PROJECT_DIR\$MAIN_CODE.elf"

编译选项

1
2
3
4
5
6
7
8
9
10
11
12
# OPTIONS
$CFLAGS = @(
"-O3", # 启用最高级别优化
"-nostdlib", # 禁用标准库链接
"-flto", # 链接时优化
"-ffreestanding", # 独立环境编译
"-ffunction-sections", # 函数分段,配合链接器GC移除未使用函数
"-fdata-sections", # 数据分段,支持链接时移除未用数据
"-fno-builtin", # 禁用内置函数
"--specs=nano.specs", # 轻量库配置
"--specs=nosys.specs" # 无系统调用配置
)
  • 性能强化:编译、链接双阶段优化
    • -O3+-flto
  • 裸机环境适配:确保编译结果不依赖操作系统
    • -nostdlib+-ffreestanding+nosys.specs
  • 代码尺寸优化:移除未使用代码、数据
    • -ffunction-sections+-fdata-sections
  • 精简库:减小二进制体积
    • nano.specs

链接选项

1
2
3
4
5
6
7
$LDFLAGS = @(
"-Wl,--build-id=none", # 禁用构建ID,减少二进制体积
"-Wl,-Bstatic", # 强制静态链接
"-Wl,-T,$LINKER_SCRIPT", # 指定链接脚本,自定以内存布局
"-Wl,-Map=$MAP_FILE", # 生成链接映射,用于调试与内存分析
"-L." # 添加库搜索路径
)
  • 部署控制:强制静态链接(-Bstatic)和自定义内存布局(-T脚本)确保程序在目标硬件精确运行

编译命令

1
2
3
4
5
# COMPILE
& $RISCV_GCC -march=rv32e -mabi=ilp32e $CFLAGS $LDFLAGS -o $ELF_OUTPUT $SOURCE_FILES
& $OBJDUMP -S $ELF_OUTPUT > ($ELF_OUTPUT -replace '\.elf$', '.s')
& $OBJCOPY -O binary $ELF_OUTPUT ($ELF_OUTPUT -replace '\.elf$', '.bin')
& $OBJCOPY -O verilog --verilog-data-width 4 $ELF_OUTPUT ($ELF_OUTPUT -replace '\.elf$', '.hex')

GUI开发

工具准备

原型

  • Eclipse新建Java Project,不勾选Create module-info.java
  • 先实现调用本地GCC的GUI原型,再封装GCC及GUI
  • Java GUI代码开源于我的GitHub仓库
    • SSH地址:git@github.com:arvinhwo/RISC-V-GCC-GUI.git
  • 试运行

image-20250807134828543

封装

  • 将RISCV GCC和Java环境封装进安装包,达到开箱即用的目的

GCC打包

  • 将编译工具链放入项目根目录并改名toolchain
    • 目录结构为riscv_compiler/toolchain/bin/riscv-none-elf-gcc.exe
  • 将原型中工具链路径由用户输入改为自动获取

JAR打包

  • 打包为Runnable JAR file类型
    • 选择主类入口RiscvCompilerGUI - risv_compiler
    • 打包依赖项Package required libraries into generated JAR
    • 目录结构为riscv_compiler/RiscvCompiler.jar

image-20250808102045734

  • 使用JDK自带的jlink在项目目录中生成精简JRE,使封装后的GUI能在无JDK的环境中运行
    • JDK添加到环境变量后,jlink --module-path jmods --add-modules java.base,java.desktop --output jre
    • 目录结构为riscv_compiler/jre/bin/java.exe
    • CMD验证JREjre\bin\java.exe -jar RiscvCompiler.jar

image-20250808103451834

EXE打包

  • 在项目目录中新建setup.iss文件,使用Inno Setup打开并编译
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
[Setup]
AppName=RISC-V Compiler Suite
AppVersion=1.0
DefaultDirName={pf}\RiscvCompiler
OutputDir=.\Output
OutputBaseFilename=RiscvCompiler_Setup
Compression=lzma2
SolidCompression=yes
ArchitecturesAllowed=x64
ArchitecturesInstallIn64BitMode=x64

[Files]
Source: ".\RiscvCompiler.jar"; DestDir: "{app}"; Flags: ignoreversion
Source: ".\toolchain\*"; DestDir: "{app}\toolchain"; Flags: ignoreversion recursesubdirs
Source: ".\jre\*"; DestDir: "{app}\jre"; Flags: ignoreversion recursesubdirs

[Icons]
Name: "{commondesktop}\RISC-V Compiler"; Filename: "{app}\RiscvCompiler.bat"; IconFilename: "{app}\compiler_icon.ico"
Name: "{commonprograms}\RISC-V Compiler"; Filename: "{app}\RiscvCompiler.bat"; IconFilename: "{app}\compiler_icon.ico"

[Run]
Filename: "{app}\RiscvCompiler.bat"; Description: "启动编译器"; Flags: postinstall nowait skipifsilent

[Code]
// 创建强制使用内置JRE的启动脚本
procedure CreateBatchFile;
var
BatchFile: string;
begin
BatchFile := ExpandConstant('{app}\RiscvCompiler.bat');
SaveStringToFile(BatchFile,
'@echo off' + #13#10 +
'set APPDIR=%~dp0' + #13#10 +
'start "" "%APPDIR%jre\bin\javaw.exe" -jar "%APPDIR%RiscvCompiler.jar"' + #13#10,
False
);
end;

procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssPostInstall then
CreateBatchFile;
end;