使用Cargo与自定义链接器

使用Cargo与自定义链接器

问题描述:

我想使用cargo来构建需要自定义编译的项目(调用汇编器,链接器...)。使用Cargo与自定义链接器

我能够使用构建脚本来做到这一点,但它并不完美。例如,建立从这个tutorial的代码中,我提出了以下构建脚本:

use std::fs::create_dir; 
use std::process::Command; 

fn main() { 
    build(); 
    link(); 
    iso(); 
} 

fn build() { 
    Command::new("cargo") 
     .current_dir("uefi_app") 
     .args(&["rustc", "--", "--emit", "obj"]) 
     .status().unwrap(); 
} 

fn iso() { 
    let disk_file = "target/debug/disk.img"; 
    let disk_dir = "target/debug/disk"; 
    let efi_boot = disk_dir.to_owned() + "/efi/boot"; 
    let copy_dest = efi_boot.clone() + "/bootx64.efi"; 

    let dd_of = "of=".to_owned() + disk_file; 
    Command::new("dd") 
     .args(&["if=/dev/zero", &dd_of, "bs=512", "count=93750"]) 
     .status().unwrap(); 

    Command::new("parted") 
     .args(&[disk_file, "-s", "-a", "minimal", "mklabel", "gpt"]) 
     .status().unwrap(); 

    Command::new("parted") 
     .args(&[disk_file, "-s", "-a", "minimal", "mkpart", "EFI", "FAT16", "2048s", "93716s"]) 
     .status().unwrap(); 

    Command::new("parted") 
     .args(&[disk_file, "-s", "-a", "minimal", "toggle", "1", "boot"]) 
     .status().unwrap(); 

    Command::new("sudo") 
     .args(&["losetup", "--offset", "1048576", "--sizelimit", "46934528", "/dev/loop0", disk_file]) 
     .status().unwrap(); 

    let _ = create_dir(disk_dir); 

    Command::new("sudo") 
     .args(&["mkdosfs", "-F", "32", "/dev/loop0"]) 
     .status().unwrap(); 

    Command::new("sudo") 
     .args(&["mount", "/dev/loop0", disk_dir]) 
     .status().unwrap(); 

    Command::new("sudo") 
     .args(&["mkdir", "-p", &efi_boot]) 
     .status().unwrap(); 

    Command::new("sudo") 
     .args(&["cp", "target/debug/boot.efi", &copy_dest]) 
     .status().unwrap(); 

    Command::new("sudo") 
     .args(&["umount", disk_dir]) 
     .status().unwrap(); 

    Command::new("sudo") 
     .args(&["losetup", "-d", "/dev/loop0"]) 
     .status().unwrap(); 

    Command::new("sudo") 
     .args(&["rm", "-R", disk_dir]) 
     .status().unwrap(); 
} 

fn link() { 
    Command::new("x86_64-efi-pe-ld") 
     .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(); 
} 

你可以看到完整的箱子here

另一个例子是this cratehere的操作系统教程。

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

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

我怎样才能使用货物来自动化这样的汇编?

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

+0

你的标题说,“自定义链接”,但这个问题好像是问关于全面落实构建系统,如制作。你可能想尝试同步这两件事。另外,这不是真正的[build script for](http://doc.crates.io/build-script.html),这可能解释了递归问题。 – Shepmaster

+0

@Sephmaster如果我只是要求使用另一个链接器,它会是更好的问题吗? – antoyo

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

[target.thumbv7em-none-eabi] 
linker = "arm-none-eabi-gcc" 
ar = "arm-none-eabi-ar"