【问题标题】:Use Cargo with a custom linker使用带有自定义链接器的 Cargo
【发布时间】:2016-09-05 04:25:08
【问题描述】:

我想使用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 crate 来自here 的操作系统教程。

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

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

我如何使用 cargo 来自动化这样的编译?

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

【问题讨论】:

  • 您的标题是“自定义链接器”,但问题似乎是在询问完全实现像 Make 这样的构建系统。您可能想尝试同步这两件事。此外,这并不是真正的 build scripts are for,这可能解释了递归问题。
  • @Sephmaster 如果我只要求使用另一个链接器会更好吗?

标签: rust rust-cargo


【解决方案1】:

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

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

【讨论】:

  • 我应该把这个配置文件放在哪里?
  • IIRC .cargo 目录位于项目的根目录中。即与您的 Cargo.toml 文件相同的目录。配置文件位于 .cargo 目录中。
  • 如何为所有类型的目标指定链接器?
  • 此页面解释了配置层次结构以及您可以放置​​的多个位置,具体取决于您是否要影响模块、项目、所有项目等。doc.rust-lang.org/cargo/reference/config.html
猜你喜欢
  • 2021-09-20
  • 2018-02-11
  • 2022-09-27
  • 1970-01-01
  • 2022-11-28
  • 1970-01-01
  • 1970-01-01
  • 2020-01-27
  • 1970-01-01
相关资源
最近更新 更多