From aad426a5f485cca8cf3ebec5db78d42a0a9bee64 Mon Sep 17 00:00:00 2001 From: fanyang Date: Fri, 22 May 2026 22:55:22 +0800 Subject: [PATCH] fix: support riscv64gc bindgen target --- .github/workflows/rust.yml | 6 ++++- build.rs | 53 +++++++++++++++++++++++++++++--------- 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 51676af..53697a0 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -141,7 +141,7 @@ jobs: # ────────────────────────────────────────────── # Cross-compilation via zigbuild (musl targets) - # 2 targets × 2 profiles = 4 jobs + # 3 targets × 2 profiles = 6 jobs # ────────────────────────────────────────────── cross: name: Cross ${{ matrix.target }} (${{ matrix.profile }}) @@ -158,6 +158,10 @@ jobs: profile: debug - target: x86_64-unknown-linux-musl profile: release + - target: riscv64gc-unknown-linux-musl + profile: debug + - target: riscv64gc-unknown-linux-musl + profile: release steps: - uses: actions/checkout@v4 diff --git a/build.rs b/build.rs index 3c49354..79fe6e4 100644 --- a/build.rs +++ b/build.rs @@ -4,7 +4,7 @@ use std::process::{Command, Stdio}; fn zig_target(target: &str) -> String { let mut parts = target.split('-'); - let arch = parts.next().unwrap_or(target); + let arch = clang_arch(parts.next().unwrap_or(target)); let _vendor = parts.next(); let rest = parts.collect::>(); @@ -15,17 +15,46 @@ fn zig_target(target: &str) -> String { } } +fn clang_arch(arch: &str) -> &str { + match arch { + "riscv64gc" => "riscv64", + _ => arch, + } +} + +fn clang_target(target: &str) -> String { + let mut parts = target.split('-'); + let arch = clang_arch(parts.next().unwrap_or(target)); + let rest = parts.collect::>(); + + if rest.is_empty() { + arch.to_owned() + } else { + format!("{arch}-{}", rest.join("-")) + } +} + +fn clang_target_args(target: &str) -> Vec { + let mut args = vec![format!("--target={}", clang_target(target))]; + if target.starts_with("riscv64gc-") { + args.push("-march=rv64gc".to_owned()); + } + args +} + fn zig_include_dirs(target: &str) -> Option> { + let args = [ + "cc".to_owned(), + format!("--target={}", zig_target(target)), + "-E".to_owned(), + "-x".to_owned(), + "c".to_owned(), + "-".to_owned(), + "-v".to_owned(), + ]; + let output = Command::new("zig") - .args([ - "cc", - &format!("--target={}", zig_target(target)), - "-E", - "-x", - "c", - "-", - "-v", - ]) + .args(args) .stdin(Stdio::null()) .output() .ok()?; @@ -79,7 +108,7 @@ fn generate_bindings(target: &str) { let host = env::var("HOST").unwrap(); if target != host { if is_zigbuild(target) { - bindings = bindings.clang_arg(format!("--target={}", zig_target(target))); + bindings = bindings.clang_args(clang_target_args(target)); if let Some(include_dirs) = zig_include_dirs(target) { for include_dir in include_dirs { @@ -87,7 +116,7 @@ fn generate_bindings(target: &str) { } } } else { - bindings = bindings.clang_arg(format!("--target={target}")); + bindings = bindings.clang_args(clang_target_args(target)); } }