将 Cargo 与自定义链接器一起使用

ant*_*oyo 6 rust rust-cargo

我想用来cargo构建需要自定义编译的项目(调用汇编器、链接器、\xe2\x80\xa6)。

\n\n

我可以使用构建脚本来做到这一点,但它并不完美。例如,为了构建本教程中的代码,我制作了以下构建脚本:

\n\n
use std::fs::create_dir;\nuse std::process::Command;\n\nfn main() {\n    build();\n    link();\n    iso();\n}\n\nfn build() {\n    Command::new("cargo")\n        .current_dir("uefi_app")\n        .args(&["rustc", "--", "--emit", "obj"])\n        .status().unwrap();\n}\n\nfn iso() {\n    let disk_file = "target/debug/disk.img";\n    let disk_dir = "target/debug/disk";\n    let efi_boot = disk_dir.to_owned() + "/efi/boot";\n    let copy_dest = efi_boot.clone() + "/bootx64.efi";\n\n    let dd_of = "of=".to_owned() + disk_file;\n    Command::new("dd")\n        .args(&["if=/dev/zero", &dd_of, "bs=512", "count=93750"])\n        .status().unwrap();\n\n    Command::new("parted")\n        .args(&[disk_file, "-s", "-a", "minimal", "mklabel", "gpt"])\n        .status().unwrap();\n\n    Command::new("parted")\n        .args(&[disk_file, "-s", "-a", "minimal", "mkpart", "EFI", "FAT16", "2048s", "93716s"])\n        .status().unwrap();\n\n    Command::new("parted")\n        .args(&[disk_file, "-s", "-a", "minimal", "toggle", "1", "boot"])\n        .status().unwrap();\n\n    Command::new("sudo")\n        .args(&["losetup", "--offset", "1048576", "--sizelimit", "46934528", "/dev/loop0", disk_file])\n        .status().unwrap();\n\n    let _ = create_dir(disk_dir);\n\n    Command::new("sudo")\n        .args(&["mkdosfs", "-F", "32", "/dev/loop0"])\n        .status().unwrap();\n\n    Command::new("sudo")\n        .args(&["mount", "/dev/loop0", disk_dir])\n        .status().unwrap();\n\n    Command::new("sudo")\n        .args(&["mkdir", "-p", &efi_boot])\n        .status().unwrap();\n\n    Command::new("sudo")\n        .args(&["cp", "target/debug/boot.efi", &copy_dest])\n        .status().unwrap();\n\n    Command::new("sudo")\n        .args(&["umount", disk_dir])\n        .status().unwrap();\n\n    Command::new("sudo")\n        .args(&["losetup", "-d", "/dev/loop0"])\n        .status().unwrap();\n\n    Command::new("sudo")\n        .args(&["rm", "-R", disk_dir])\n        .status().unwrap();\n}\n\nfn link() {\n    Command::new("x86_64-efi-pe-ld")\n        .args(&["--oformat", "pei-x86-64", "--subsystem", "10", "-pie", "-e", "efi_main", "uefi_app/target/debug/uefi_app.o", "-o", "target/debug/boot.efi"]).output().unwrap();\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

您可以在这里看到完整的箱子。

\n\n

另一个例子是这里的操作系统教程的箱子

\n\n

这需要一个单独的板条箱,因为在构建脚本中运行货物似乎会触发无限循环。

\n\n

这个构建脚本的问题是,cargo clean每次更新构建脚本编译的包的代码时,我都需要运行。

\n\n

我如何使用货物来自动进行这样的编译?

\n\n

我想要的只是输入cargo run并获取 ISO(或硬盘驱动器文件)并启动虚拟机。

\n

Dav*_*nds 8

您可以在 .cargo/config 文件中指定自定义链接器。以此为例:

[target.thumbv7em-none-eabi]
linker = "arm-none-eabi-gcc"
ar = "arm-none-eabi-ar"
Run Code Online (Sandbox Code Playgroud)

  • 如何为所有类型的目标指定链接器? (2认同)