将 Cargo 与自定义链接器一起使用 [英] Use Cargo with a custom linker

查看:69
本文介绍了将 Cargo 与自定义链接器一起使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I would like to use cargo to build projects requiring a custom compilation (calling the assembler, the linker, …).

我可以使用构建脚本来做到这一点,但它并不完美.例如,从这个教程构建代码,我做了以下构建脚本:

I was able to do this with a build script, but it is not perfect. For instance, to build the code from this tutorial, I made the following build script:

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();
}

您可以在此处查看完整的 crate.

You can see the complete crate here.

另一个例子是 this crate 来自 此处.

Another example is this crate for the OS tutorials from here.

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

This require a separate crate because running cargo in a build script seems to trigger an infinite loop.

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

The issue with this build script is that I need to run cargo clean everytime I update the code of the crate compiled by the build script.

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

How could I use cargo to automate such a compilation?

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

What I want is just typing cargo run and get an ISO (or harddrive file) and launch the VM.

推荐答案

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

You can specify a custom linker in the .cargo/config file. See this as an example:

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

这篇关于将 Cargo 与自定义链接器一起使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆