Compile rustc for a custom target

Hi everyone,

I am working actually on my Linux distribution. I did a package manager able to build a Linux system completely from scratch from the source.

I am just facing a small problem. I need to compile rustc for a custom target. The target I have on the system is: x86_64-horizon-linux-gnu

How should I proceed ? I guess I need to change something in the file config.toml, but after lot of try, I don't get the result I want...

This is the script called by my package manager (even you don't know the API, should be easy to understand):

class Target < ISM::Software

    def prepare
        super

        configData = <<-CODE
        changelog-seen = 2

        [llvm]
        targets = "X86"
        link-shared = true

        [build]
        full-bootstrap = true
        docs = false
        extended = true
        locked-deps = true
        tools = ["cargo", "clippy", "rustdoc", "rustfmt"]
        vendor = true

        [install]
        prefix = "/usr"
        docdir = "share/doc/rustc-1.71.1"

        [rust]
        channel = "stable"

        [target.#{Ism.settings.systemTarget}]
        llvm-config = "/usr/bin/llvm-config"
        CODE
        fileWriteData("#{buildDirectoryPath}/config.toml",configData)
    end
    
    def build
        super

        runPythonCommand(   arguments:      "./x.py build",
                            path:           buildDirectoryPath,
                            environment:    {"LIBSSH2_SYS_USE_PKG_CONFIG" => "1"})
    end
    
    def prepareInstallation
        super

        runPythonCommand(   arguments:      "./x.py install",
                            path:           buildDirectoryPath,
                            environment:    {   "DESTDIR" => "#{builtSoftwareDirectoryPath}#{Ism.settings.rootPath}",
                                                "LIBSSH2_SYS_USE_PKG_CONFIG" => "1"})

        deleteAllFilesRecursivelyFinishing( path:       "#{builtSoftwareDirectoryPath}#{Ism.settings.rootPath}",
                                            extensions: ["old"])
    end

end

This is my project page by the way: GitHub - Fulgurance/ISM: Ingenius System Manager

(Horizon will be my linux system name)

You need a target specification JSON file.

I don't have time right now to explain it to you right now but take mine as an example (it's compiling to real mode 16-bit i386):

{
  "llvm-target": "i386-unknown-none-code16",
  "data-layout": "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128",
  "arch": "x86",
  "target-endian": "little",
  "target-pointer-width": "32",
  "target-c-int-width": "32",
  "os": "none",
  "linker-flavor": "ld.lld",
  "linker": "rust-lld",
  "panic-strategy": "abort",
  "disable-redzone": true,
  "features": "-mmx,-sse,+soft-float,+16bit-mode",
  "code-model": "kernel"
}

And run this with cargo run --target your-target-spec-file.json

Is there actually anything you need to change to the target specification? Most distros just use x86_64-unknown-linux-gnu as target to compile for. The name of the target doesn't affect the compiled executables.

2 Likes

To add to what @bjorn3 said, the "vendor" component of a canonical system tuple (where you put "horizon") is a vestige of an era of bad marketing choices by Unix workstation vendors in the late 1980s. Most software ignores it. It has to stick around for backward compatibility with all the code that parses canonical system tuples, but it should always be -unknown- or -pc- for new systems.

Canonical system tuples are also intentionally not supposed to capture all the differences between systems. They stop at the level of the C library and the ABI. The questions you should ask yourself are:

  1. Presumably you are using the Linux kernel, or you would not have -linux in there. Are you also using the GNU C library? If you aren't, change the -gnu piece: -musl for musl libc, -bionic for Bionic libc, -horizon if you wrote your own, etc.
  2. Did you change the C calling convention or the size of any type defined by standard C or POSIX header files? If so, tack on a suffix (without another dash): -gnuabihorizon or something. I can be more specific if you tell me what you changed.

But if you're using glibc and you didn't change the ABI, stick to x86_64-unknown-linux-gnu.

1 Like

I have only this problem with rust actually.

All of the other softwares I compiled from scratch support a custom target. It's a bit the shame to be honest...

And the rust website support the possibility for adding new target, so it's normal I ask no ? ...

What I mean is the main goal of my distribution is to allow the user to configure everything in detail. So if rust support the possibility to add a new target, I want to do it

I'm telling you, in my capacity as the closest thing Autoconf has to a maintainer anymore, that this is not a customization point that's available to you. The canonical system name for all glibc-based Linux distributions is <cpu>-unknown-linux-gnu<abi-suffix> and you must not change this unless you are using a different C library or you have changed the ABI. So much stuff will break. Rust is just the first thing you happened to trip over.

2 Likes

Hmmm okay. Got it.

I didn't know it's was so deeply hardcoded. Thank you for your help

My condolences.

1 Like

Some Linux distros like RHEL or SUSE do change the vendor fields for their C compiler targets. I don't think they do it for Rust though, Rust doesn't really support this and that's good for everyone, there's no reason to have it be different. I'd recommend against changing the vendor field for anything.