1eba8b6baSopenharmony_ci//! A program which generates a linux-headers installation and runs bindgen
2eba8b6baSopenharmony_ci//! over the headers, for each supported architecture.
3eba8b6baSopenharmony_ci
4eba8b6baSopenharmony_ciuse bindgen::{builder, EnumVariation};
5eba8b6baSopenharmony_ciuse std::collections::HashSet;
6eba8b6baSopenharmony_ciuse std::fs::File;
7eba8b6baSopenharmony_ciuse std::io::{BufRead, BufReader, Read, Write};
8eba8b6baSopenharmony_ciuse std::path::Path;
9eba8b6baSopenharmony_ciuse std::process::Command;
10eba8b6baSopenharmony_ciuse std::{env, fs};
11eba8b6baSopenharmony_ci
12eba8b6baSopenharmony_ci#[allow(unused_doc_comments)]
13eba8b6baSopenharmony_ciconst LINUX_VERSION: &str = "v5.17";
14eba8b6baSopenharmony_ci
15eba8b6baSopenharmony_ci/// Some commonly used features.
16eba8b6baSopenharmony_ciconst DEFAULT_FEATURES: &str = "\"general\", \"errno\"";
17eba8b6baSopenharmony_ci
18eba8b6baSopenharmony_cifn main() {
19eba8b6baSopenharmony_ci    let mut args = env::args();
20eba8b6baSopenharmony_ci    let _exe = args.next().unwrap();
21eba8b6baSopenharmony_ci    let cmd = args.next();
22eba8b6baSopenharmony_ci
23eba8b6baSopenharmony_ci    // This is the main invocation path.
24eba8b6baSopenharmony_ci    assert!(cmd.is_none());
25eba8b6baSopenharmony_ci    assert!(args.next().is_none());
26eba8b6baSopenharmony_ci
27eba8b6baSopenharmony_ci    git_init();
28eba8b6baSopenharmony_ci
29eba8b6baSopenharmony_ci    let out = tempdir::TempDir::new("linux-raw-sys").unwrap();
30eba8b6baSopenharmony_ci    let out_dir = out.path();
31eba8b6baSopenharmony_ci    let linux_headers = out_dir.join("linux-headers");
32eba8b6baSopenharmony_ci    let linux_include = linux_headers.join("include");
33eba8b6baSopenharmony_ci
34eba8b6baSopenharmony_ci    // Clean up any modules from previous builds.
35eba8b6baSopenharmony_ci    for entry in fs::read_dir("../src").unwrap() {
36eba8b6baSopenharmony_ci        let entry = entry.unwrap();
37eba8b6baSopenharmony_ci        assert!(!entry.path().to_str().unwrap().ends_with("."));
38eba8b6baSopenharmony_ci        if entry.file_type().unwrap().is_dir() {
39eba8b6baSopenharmony_ci            fs::remove_dir_all(entry.path()).ok();
40eba8b6baSopenharmony_ci        }
41eba8b6baSopenharmony_ci    }
42eba8b6baSopenharmony_ci
43eba8b6baSopenharmony_ci    // Edit ../src/lib.rs
44eba8b6baSopenharmony_ci    let mut src_lib_rs_in = File::open("../src/lib.rs").unwrap();
45eba8b6baSopenharmony_ci    let mut src_lib_rs_contents = String::new();
46eba8b6baSopenharmony_ci    src_lib_rs_in
47eba8b6baSopenharmony_ci        .read_to_string(&mut src_lib_rs_contents)
48eba8b6baSopenharmony_ci        .unwrap();
49eba8b6baSopenharmony_ci    let edit_at = src_lib_rs_contents
50eba8b6baSopenharmony_ci        .find("// The rest of this file is auto-generated!\n")
51eba8b6baSopenharmony_ci        .unwrap();
52eba8b6baSopenharmony_ci    src_lib_rs_contents = src_lib_rs_contents[..edit_at].to_owned();
53eba8b6baSopenharmony_ci
54eba8b6baSopenharmony_ci    let mut src_lib_rs = File::create("../src/lib.rs").unwrap();
55eba8b6baSopenharmony_ci    src_lib_rs
56eba8b6baSopenharmony_ci        .write_all(src_lib_rs_contents.as_bytes())
57eba8b6baSopenharmony_ci        .unwrap();
58eba8b6baSopenharmony_ci    src_lib_rs
59eba8b6baSopenharmony_ci        .write_all("// The rest of this file is auto-generated!\n".as_bytes())
60eba8b6baSopenharmony_ci        .unwrap();
61eba8b6baSopenharmony_ci
62eba8b6baSopenharmony_ci    // Edit ../Cargo.toml
63eba8b6baSopenharmony_ci    let mut cargo_toml_in = File::open("../Cargo.toml").unwrap();
64eba8b6baSopenharmony_ci    let mut cargo_toml_contents = String::new();
65eba8b6baSopenharmony_ci    cargo_toml_in
66eba8b6baSopenharmony_ci        .read_to_string(&mut cargo_toml_contents)
67eba8b6baSopenharmony_ci        .unwrap();
68eba8b6baSopenharmony_ci    let edit_at = cargo_toml_contents
69eba8b6baSopenharmony_ci        .find("# The rest of this file is auto-generated!\n")
70eba8b6baSopenharmony_ci        .unwrap();
71eba8b6baSopenharmony_ci    cargo_toml_contents = cargo_toml_contents[..edit_at].to_owned();
72eba8b6baSopenharmony_ci
73eba8b6baSopenharmony_ci    // Generate Cargo.toml
74eba8b6baSopenharmony_ci    let mut cargo_toml = File::create("../Cargo.toml").unwrap();
75eba8b6baSopenharmony_ci    cargo_toml
76eba8b6baSopenharmony_ci        .write_all(cargo_toml_contents.as_bytes())
77eba8b6baSopenharmony_ci        .unwrap();
78eba8b6baSopenharmony_ci    cargo_toml
79eba8b6baSopenharmony_ci        .write_all("# The rest of this file is auto-generated!\n".as_bytes())
80eba8b6baSopenharmony_ci        .unwrap();
81eba8b6baSopenharmony_ci    writeln!(cargo_toml, "[features]").unwrap();
82eba8b6baSopenharmony_ci
83eba8b6baSopenharmony_ci    let mut features: HashSet<String> = HashSet::new();
84eba8b6baSopenharmony_ci
85eba8b6baSopenharmony_ci    let linux_version = LINUX_VERSION;
86eba8b6baSopenharmony_ci    // Checkout a specific version of Linux.
87eba8b6baSopenharmony_ci    git_checkout(linux_version);
88eba8b6baSopenharmony_ci
89eba8b6baSopenharmony_ci    let mut linux_archs = fs::read_dir(&format!("linux/arch"))
90eba8b6baSopenharmony_ci        .unwrap()
91eba8b6baSopenharmony_ci        .map(|entry| entry.unwrap())
92eba8b6baSopenharmony_ci        .collect::<Vec<_>>();
93eba8b6baSopenharmony_ci    // Sort archs list as filesystem iteration order is non-deterministic
94eba8b6baSopenharmony_ci    linux_archs.sort_by_key(|entry| entry.file_name());
95eba8b6baSopenharmony_ci    for linux_arch_entry in linux_archs {
96eba8b6baSopenharmony_ci        if !linux_arch_entry.file_type().unwrap().is_dir() {
97eba8b6baSopenharmony_ci            continue;
98eba8b6baSopenharmony_ci        }
99eba8b6baSopenharmony_ci        let linux_arch = linux_arch_entry.file_name().to_str().unwrap().to_owned();
100eba8b6baSopenharmony_ci
101eba8b6baSopenharmony_ci        let rust_arches = rust_arches(&linux_arch);
102eba8b6baSopenharmony_ci        if rust_arches.is_empty() {
103eba8b6baSopenharmony_ci            continue;
104eba8b6baSopenharmony_ci        }
105eba8b6baSopenharmony_ci
106eba8b6baSopenharmony_ci        fs::create_dir_all(&linux_headers).unwrap();
107eba8b6baSopenharmony_ci
108eba8b6baSopenharmony_ci        let mut headers_made = false;
109eba8b6baSopenharmony_ci        for rust_arch in rust_arches {
110eba8b6baSopenharmony_ci            if !headers_made {
111eba8b6baSopenharmony_ci                make_headers_install(&linux_arch, &linux_headers);
112eba8b6baSopenharmony_ci                headers_made = true;
113eba8b6baSopenharmony_ci            }
114eba8b6baSopenharmony_ci
115eba8b6baSopenharmony_ci            eprintln!(
116eba8b6baSopenharmony_ci                "Generating all bindings for Linux {} architecture {}",
117eba8b6baSopenharmony_ci                linux_version, rust_arch
118eba8b6baSopenharmony_ci            );
119eba8b6baSopenharmony_ci
120eba8b6baSopenharmony_ci            let src_arch = format!("../src/{}", rust_arch);
121eba8b6baSopenharmony_ci
122eba8b6baSopenharmony_ci            fs::create_dir_all(&src_arch).unwrap();
123eba8b6baSopenharmony_ci
124eba8b6baSopenharmony_ci            let mut modules = fs::read_dir("modules")
125eba8b6baSopenharmony_ci                .unwrap()
126eba8b6baSopenharmony_ci                .map(|entry| entry.unwrap())
127eba8b6baSopenharmony_ci                .collect::<Vec<_>>();
128eba8b6baSopenharmony_ci            // Sort module list as filesystem iteration order is non-deterministic
129eba8b6baSopenharmony_ci            modules.sort_by_key(|entry| entry.file_name());
130eba8b6baSopenharmony_ci            for mod_entry in modules {
131eba8b6baSopenharmony_ci                let header_name = mod_entry.path();
132eba8b6baSopenharmony_ci                let mod_name = header_name.file_stem().unwrap().to_str().unwrap();
133eba8b6baSopenharmony_ci                let mod_rs = format!("{}/{}.rs", src_arch, mod_name);
134eba8b6baSopenharmony_ci
135eba8b6baSopenharmony_ci                writeln!(src_lib_rs, "#[cfg(feature = \"{}\")]", mod_name).unwrap();
136eba8b6baSopenharmony_ci                if *rust_arch == "x32" {
137eba8b6baSopenharmony_ci                    writeln!(src_lib_rs, "#[cfg(all(target_arch = \"x86_64\", target_pointer_width = \"32\"))]").unwrap();
138eba8b6baSopenharmony_ci                } else if *rust_arch == "x86_64" {
139eba8b6baSopenharmony_ci                    writeln!(src_lib_rs, "#[cfg(all(target_arch = \"x86_64\", target_pointer_width = \"64\"))]").unwrap();
140eba8b6baSopenharmony_ci                } else {
141eba8b6baSopenharmony_ci                    writeln!(src_lib_rs, "#[cfg(target_arch = \"{}\")]", rust_arch).unwrap();
142eba8b6baSopenharmony_ci                }
143eba8b6baSopenharmony_ci                writeln!(src_lib_rs, "#[path = \"{}/{}.rs\"]", rust_arch, mod_name).unwrap();
144eba8b6baSopenharmony_ci                writeln!(src_lib_rs, "pub mod {};", mod_name).unwrap();
145eba8b6baSopenharmony_ci
146eba8b6baSopenharmony_ci                run_bindgen(
147eba8b6baSopenharmony_ci                    linux_include.to_str().unwrap(),
148eba8b6baSopenharmony_ci                    header_name.to_str().unwrap(),
149eba8b6baSopenharmony_ci                    &mod_rs,
150eba8b6baSopenharmony_ci                    mod_name,
151eba8b6baSopenharmony_ci                    rust_arch,
152eba8b6baSopenharmony_ci                    linux_version,
153eba8b6baSopenharmony_ci                );
154eba8b6baSopenharmony_ci
155eba8b6baSopenharmony_ci                // Collect all unique feature names across all architectures.
156eba8b6baSopenharmony_ci                if features.insert(mod_name.to_owned()) {
157eba8b6baSopenharmony_ci                    writeln!(cargo_toml, "{} = []", mod_name).unwrap();
158eba8b6baSopenharmony_ci                }
159eba8b6baSopenharmony_ci            }
160eba8b6baSopenharmony_ci        }
161eba8b6baSopenharmony_ci
162eba8b6baSopenharmony_ci        fs::remove_dir_all(&linux_headers).unwrap();
163eba8b6baSopenharmony_ci    }
164eba8b6baSopenharmony_ci
165eba8b6baSopenharmony_ci    writeln!(cargo_toml, "default = [\"std\", {}]", DEFAULT_FEATURES).unwrap();
166eba8b6baSopenharmony_ci    writeln!(cargo_toml, "std = []").unwrap();
167eba8b6baSopenharmony_ci    writeln!(cargo_toml, "no_std = []").unwrap();
168eba8b6baSopenharmony_ci    writeln!(
169eba8b6baSopenharmony_ci        cargo_toml,
170eba8b6baSopenharmony_ci        "rustc-dep-of-std = [\"core\", \"compiler_builtins\", \"no_std\"]"
171eba8b6baSopenharmony_ci    )
172eba8b6baSopenharmony_ci    .unwrap();
173eba8b6baSopenharmony_ci
174eba8b6baSopenharmony_ci    eprintln!("All bindings generated!");
175eba8b6baSopenharmony_ci}
176eba8b6baSopenharmony_ci
177eba8b6baSopenharmony_cifn git_init() {
178eba8b6baSopenharmony_ci    // Clone the linux kernel source repo if necessary. Ignore exit code as it will
179eba8b6baSopenharmony_ci    // be non-zero in case it was already cloned.
180eba8b6baSopenharmony_ci    //
181eba8b6baSopenharmony_ci    // Use a treeless partial clone to save disk space and clone time.
182eba8b6baSopenharmony_ci    // See <https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/>
183eba8b6baSopenharmony_ci    // for more info on partial clones.
184eba8b6baSopenharmony_ci    //
185eba8b6baSopenharmony_ci    // Note: this is not using the official repo
186eba8b6baSopenharmony_ci    // <git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git> but
187eba8b6baSopenharmony_ci    // the github fork as the server of the official repo doesn't recognize
188eba8b6baSopenharmony_ci    // filtering.
189eba8b6baSopenharmony_ci    if !Path::new("linux/.git").exists() {
190eba8b6baSopenharmony_ci        assert!(Command::new("git")
191eba8b6baSopenharmony_ci            .arg("clone")
192eba8b6baSopenharmony_ci            .arg("https://github.com/torvalds/linux.git")
193eba8b6baSopenharmony_ci            .arg("--filter=tree:0")
194eba8b6baSopenharmony_ci            .arg("--no-checkout")
195eba8b6baSopenharmony_ci            .status()
196eba8b6baSopenharmony_ci            .unwrap()
197eba8b6baSopenharmony_ci            .success());
198eba8b6baSopenharmony_ci    }
199eba8b6baSopenharmony_ci
200eba8b6baSopenharmony_ci    // Setup sparse checkout. This greatly reduces the amount of objects necessary
201eba8b6baSopenharmony_ci    // to checkout the tree.
202eba8b6baSopenharmony_ci    assert!(Command::new("git")
203eba8b6baSopenharmony_ci        .arg("sparse-checkout")
204eba8b6baSopenharmony_ci        .arg("init")
205eba8b6baSopenharmony_ci        .current_dir("linux")
206eba8b6baSopenharmony_ci        .status()
207eba8b6baSopenharmony_ci        .unwrap()
208eba8b6baSopenharmony_ci        .success());
209eba8b6baSopenharmony_ci
210eba8b6baSopenharmony_ci    fs::write(
211eba8b6baSopenharmony_ci        "linux/.git/info/sparse-checkout",
212eba8b6baSopenharmony_ci        "/*
213eba8b6baSopenharmony_ci!/*/
214eba8b6baSopenharmony_ci/include/
215eba8b6baSopenharmony_ci/arch/
216eba8b6baSopenharmony_ci/scripts/
217eba8b6baSopenharmony_ci/tools/",
218eba8b6baSopenharmony_ci    )
219eba8b6baSopenharmony_ci    .unwrap();
220eba8b6baSopenharmony_ci}
221eba8b6baSopenharmony_ci
222eba8b6baSopenharmony_cifn git_checkout(rev: &str) {
223eba8b6baSopenharmony_ci    // Delete any generated files from previous versions.
224eba8b6baSopenharmony_ci    assert!(Command::new("git")
225eba8b6baSopenharmony_ci        .arg("clean")
226eba8b6baSopenharmony_ci        .arg("-f")
227eba8b6baSopenharmony_ci        .arg("-d")
228eba8b6baSopenharmony_ci        .current_dir("linux")
229eba8b6baSopenharmony_ci        .status()
230eba8b6baSopenharmony_ci        .unwrap()
231eba8b6baSopenharmony_ci        .success());
232eba8b6baSopenharmony_ci
233eba8b6baSopenharmony_ci    // Check out the given revision.
234eba8b6baSopenharmony_ci    assert!(Command::new("git")
235eba8b6baSopenharmony_ci        .arg("checkout")
236eba8b6baSopenharmony_ci        .arg(rev)
237eba8b6baSopenharmony_ci        .arg("-f")
238eba8b6baSopenharmony_ci        .current_dir("linux")
239eba8b6baSopenharmony_ci        .status()
240eba8b6baSopenharmony_ci        .unwrap()
241eba8b6baSopenharmony_ci        .success());
242eba8b6baSopenharmony_ci
243eba8b6baSopenharmony_ci    // Delete any untracked generated files from previous versions.
244eba8b6baSopenharmony_ci    assert!(Command::new("git")
245eba8b6baSopenharmony_ci        .arg("clean")
246eba8b6baSopenharmony_ci        .arg("-f")
247eba8b6baSopenharmony_ci        .arg("-d")
248eba8b6baSopenharmony_ci        .current_dir("linux")
249eba8b6baSopenharmony_ci        .status()
250eba8b6baSopenharmony_ci        .unwrap()
251eba8b6baSopenharmony_ci        .success());
252eba8b6baSopenharmony_ci}
253eba8b6baSopenharmony_ci
254eba8b6baSopenharmony_cifn make_headers_install(linux_arch: &str, linux_headers: &Path) {
255eba8b6baSopenharmony_ci    assert!(Command::new("make")
256eba8b6baSopenharmony_ci        .arg(format!("headers_install"))
257eba8b6baSopenharmony_ci        .arg(format!("ARCH={}", linux_arch))
258eba8b6baSopenharmony_ci        .arg(format!(
259eba8b6baSopenharmony_ci            "INSTALL_HDR_PATH={}",
260eba8b6baSopenharmony_ci            fs::canonicalize(&linux_headers).unwrap().to_str().unwrap()
261eba8b6baSopenharmony_ci        ))
262eba8b6baSopenharmony_ci        .current_dir("linux")
263eba8b6baSopenharmony_ci        .status()
264eba8b6baSopenharmony_ci        .unwrap()
265eba8b6baSopenharmony_ci        .success());
266eba8b6baSopenharmony_ci}
267eba8b6baSopenharmony_ci
268eba8b6baSopenharmony_cifn rust_arches(linux_arch: &str) -> &[&str] {
269eba8b6baSopenharmony_ci    match linux_arch {
270eba8b6baSopenharmony_ci        "arm" => &["arm"],
271eba8b6baSopenharmony_ci        "arm64" => &["aarch64"],
272eba8b6baSopenharmony_ci        "avr32" => &["avr"],
273eba8b6baSopenharmony_ci        // hexagon gets build errors; disable it for now
274eba8b6baSopenharmony_ci        "hexagon" => &[],
275eba8b6baSopenharmony_ci        "mips" => &["mips", "mips64"],
276eba8b6baSopenharmony_ci        "powerpc" => &["powerpc", "powerpc64"],
277eba8b6baSopenharmony_ci        "riscv" => &["riscv32", "riscv64"],
278eba8b6baSopenharmony_ci        "s390" => &["s390x"],
279eba8b6baSopenharmony_ci        "sparc" => &["sparc", "sparc64"],
280eba8b6baSopenharmony_ci        "x86" => &["x86", "x86_64", "x32"],
281eba8b6baSopenharmony_ci        "alpha" | "cris" | "h8300" | "m68k" | "microblaze" | "mn10300" | "score" | "blackfin"
282eba8b6baSopenharmony_ci        | "frv" | "ia64" | "m32r" | "m68knommu" | "parisc" | "sh" | "um" | "xtensa"
283eba8b6baSopenharmony_ci        | "unicore32" | "c6x" | "nios2" | "openrisc" | "csky" | "arc" | "nds32" | "metag"
284eba8b6baSopenharmony_ci        | "tile" => &[],
285eba8b6baSopenharmony_ci        _ => panic!("unrecognized arch: {}", linux_arch),
286eba8b6baSopenharmony_ci    }
287eba8b6baSopenharmony_ci}
288eba8b6baSopenharmony_ci
289eba8b6baSopenharmony_cifn run_bindgen(
290eba8b6baSopenharmony_ci    linux_include: &str,
291eba8b6baSopenharmony_ci    header_name: &str,
292eba8b6baSopenharmony_ci    mod_rs: &str,
293eba8b6baSopenharmony_ci    mod_name: &str,
294eba8b6baSopenharmony_ci    rust_arch: &str,
295eba8b6baSopenharmony_ci    linux_version: &str,
296eba8b6baSopenharmony_ci) {
297eba8b6baSopenharmony_ci    let clang_target = compute_clang_target(rust_arch);
298eba8b6baSopenharmony_ci
299eba8b6baSopenharmony_ci    eprintln!(
300eba8b6baSopenharmony_ci        "Generating bindings for {} on Linux {} architecture {}",
301eba8b6baSopenharmony_ci        mod_name, linux_version, rust_arch
302eba8b6baSopenharmony_ci    );
303eba8b6baSopenharmony_ci
304eba8b6baSopenharmony_ci    let mut builder = builder()
305eba8b6baSopenharmony_ci        // The generated bindings are quite large, so use a few simple options
306eba8b6baSopenharmony_ci        // to keep the file sizes down.
307eba8b6baSopenharmony_ci        .rustfmt_configuration_file(Some(Path::new("bindgen-rustfmt.toml").to_owned()))
308eba8b6baSopenharmony_ci        .layout_tests(false)
309eba8b6baSopenharmony_ci        .generate_comments(false)
310eba8b6baSopenharmony_ci        .default_enum_style(EnumVariation::Rust {
311eba8b6baSopenharmony_ci            non_exhaustive: true,
312eba8b6baSopenharmony_ci        })
313eba8b6baSopenharmony_ci        .array_pointers_in_arguments(true)
314eba8b6baSopenharmony_ci        .derive_debug(true)
315eba8b6baSopenharmony_ci        .clang_arg(&format!("--target={}", clang_target))
316eba8b6baSopenharmony_ci        .clang_arg("-DBITS_PER_LONG=(__SIZEOF_LONG__*__CHAR_BIT__)")
317eba8b6baSopenharmony_ci        .clang_arg("-nostdinc")
318eba8b6baSopenharmony_ci        .clang_arg("-I")
319eba8b6baSopenharmony_ci        .clang_arg(linux_include)
320eba8b6baSopenharmony_ci        .clang_arg("-I")
321eba8b6baSopenharmony_ci        .clang_arg("include")
322eba8b6baSopenharmony_ci        .blocklist_item("NULL");
323eba8b6baSopenharmony_ci
324eba8b6baSopenharmony_ci    // Avoid duplicating ioctl names in the `general` module.
325eba8b6baSopenharmony_ci    if mod_name == "general" {
326eba8b6baSopenharmony_ci        for ioctl in BufReader::new(File::open("ioctl/generated.txt").unwrap()).lines() {
327eba8b6baSopenharmony_ci            builder = builder.blocklist_item(ioctl.unwrap());
328eba8b6baSopenharmony_ci        }
329eba8b6baSopenharmony_ci    }
330eba8b6baSopenharmony_ci
331eba8b6baSopenharmony_ci    let bindings = builder
332eba8b6baSopenharmony_ci        .use_core()
333eba8b6baSopenharmony_ci        .ctypes_prefix("crate::ctypes")
334eba8b6baSopenharmony_ci        .header(header_name)
335eba8b6baSopenharmony_ci        .generate()
336eba8b6baSopenharmony_ci        .expect(&format!("generate bindings for {}", mod_name));
337eba8b6baSopenharmony_ci    bindings
338eba8b6baSopenharmony_ci        .write_to_file(mod_rs)
339eba8b6baSopenharmony_ci        .expect(&format!("write_to_file for {}", mod_name));
340eba8b6baSopenharmony_ci}
341eba8b6baSopenharmony_ci
342eba8b6baSopenharmony_cifn compute_clang_target(rust_arch: &str) -> String {
343eba8b6baSopenharmony_ci    if rust_arch == "x86" {
344eba8b6baSopenharmony_ci        format!("i686-unknown-linux")
345eba8b6baSopenharmony_ci    } else if rust_arch == "x32" {
346eba8b6baSopenharmony_ci        format!("x86_64-unknown-linux-gnux32")
347eba8b6baSopenharmony_ci    } else {
348eba8b6baSopenharmony_ci        format!("{}-unknown-linux", rust_arch)
349eba8b6baSopenharmony_ci    }
350eba8b6baSopenharmony_ci}
351