<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>kx</title>
    <link>https://wf.fosstodon.su/kx/</link>
    <description></description>
    <pubDate>Tue, 21 Apr 2026 14:57:12 +0300</pubDate>
    <item>
      <title>Rust Custom Triplet</title>
      <link>https://wf.fosstodon.su/kx/rust-custom-triplet</link>
      <description>&lt;![CDATA[Целевые триплеты описывают платформу, на которой выполняется код, и являются основной концепцией системы сборки GNU. Обычно триплет содержит три поля: название семейства/модели CPU, поставщика и имя операционной системы. Кроме того, триплет может иметь дополнительное поле, отражающее Application Binary Interface (ABI), например: gnu, gnueabihf, gnuilp32.&#xA;&#xA;Rust Custom Triplet&#xA;&#xA;Просмотреть целевой триплет текущей системы можно с помощью команды `gcc -dumpmachine&#39;:&#xA;&#xA;bash-5.1$ gcc -dumpmachine&#xA;x8664-slackware-linux&#xA;&#xA;Если вы создаете новую систему или собственный GNU/Linux дистрибутив, у вас может возникнуть необходимость иметь собственный целевой триплет. Например, x8664-radix-linux-gnu для CPU Intel или AMD.&#xA;&#xA;При создании инструментария (toolchain-а) на базе GCC все выглядит элементарно. Достаточно сконфигурировать binutils с опцией --enable-targets=x8664-radix-linux-gnu. Однако добавление собственного триплета компиляторов LLVM и Rust выглядит уже не совсем тривиально.&#xA;&#xA;Здесь мы рассмотрим добавление нового триплета инструментария языка Rust.&#xA;&#xA;Прежде всего необходимо загрузить исходный код:&#xA;&#xA;git clone https://github.com/rust-lang/rust.git rust-1.82.0&#xA;( cd rust-1.82.0&#xA;  git checkout -b 1.82.0 tags/1.82.0&#xA;  git submodule update --init --recursive )&#xA;&#xA;Поскольку репозиторий исходного кода Rust содержит исходный код проекта LLVM, мы сможем одновременно рассмотреть добавление нового триплета и для случая LLVM, и для случая Rust.&#xA;&#xA;LLVM Project&#xA;&#xA;Итак, для того чтобы добавить новый триплет компилятору clang нам необходимо внести изменения в файлы:&#xA;&#xA;rust-1.82.0/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp&#xA;rust-1.82.0/src/llvm-project/llvm/include/llvm/TargetParser/Triple.h&#xA;rust-1.82.0/src/llvm-project/llvm/lib/TargetParser/Triple.cpp&#xA;&#xA;Патч для Rust 1.82.0 представлен на следующем листинге:&#xA;&#xA;diff --unified -Nr rust-1.82.0-orig/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp rust-1.82.0/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp&#xA;--- rust-1.82.0-orig/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp&#x9;2024-11-10 22:33:14.000000000 +0300&#xA;+++ rust-1.82.0/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp&#x9;2024-11-11 01:34:23.586151730 +0300&#xA;@@ -2491,7 +2491,7 @@&#xA;       &#34;x8664-linux-gnu&#34;,       &#34;x8664-unknown-linux-gnu&#34;,&#xA;       &#34;x8664-pc-linux-gnu&#34;,    &#34;x8664-redhat-linux6E&#34;,&#xA;       &#34;x8664-redhat-linux&#34;,    &#34;x8664-suse-linux&#34;,&#xA;&#34;x8664-manbo-linux-gnu&#34;, &#34;x8664-slackware-linux&#34;,&#xA;&#34;x8664-manbo-linux-gnu&#34;, &#34;x8664-slackware-linux&#34;, &#34;x8664-radix-linux-gnu&#34;,&#xA;       &#34;x8664-unknown-linux&#34;,   &#34;x8664-amazon-linux&#34;};&#xA;   static const char *const X32Triples[] = {&#34;x8664-linux-gnux32&#34;,&#xA;                                            &#34;x8664-pc-linux-gnux32&#34;};&#xA;diff --unified -Nr rust-1.82.0-orig/src/llvm-project/llvm/include/llvm/TargetParser/Triple.h rust-1.82.0/src/llvm-project/llvm/include/llvm/TargetParser/Triple.h&#xA;--- rust-1.82.0-orig/src/llvm-project/llvm/include/llvm/TargetParser/Triple.h&#x9;2024-11-10 22:33:17.000000000 +0300&#xA;+++ rust-1.82.0/src/llvm-project/llvm/include/llvm/TargetParser/Triple.h&#x9;2024-11-11 01:34:23.585151730 +0300&#xA;@@ -183,6 +183,7 @@&#xA; &#xA;     Apple,&#xA;     PC,&#xA;Radix,&#xA;     SCEI,&#xA;     Freescale,&#xA;     IBM,&#xA;diff --unified -Nr rust-1.82.0-orig/src/llvm-project/llvm/lib/TargetParser/Triple.cpp rust-1.82.0/src/llvm-project/llvm/lib/TargetParser/Triple.cpp&#xA;--- rust-1.82.0-orig/src/llvm-project/llvm/lib/TargetParser/Triple.cpp&#x9;2024-11-10 22:33:17.000000000 +0300&#xA;+++ rust-1.82.0/src/llvm-project/llvm/lib/TargetParser/Triple.cpp&#x9;2024-11-11 01:34:23.585151730 +0300&#xA;@@ -251,6 +251,7 @@&#xA;   case NVIDIA: return &#34;nvidia&#34;;&#xA;   case OpenEmbedded: return &#34;oe&#34;;&#xA;   case PC: return &#34;pc&#34;;&#xA;case Radix: return &#34;radix&#34;;&#xA;   case SCEI: return &#34;scei&#34;;&#xA;   case SUSE: return &#34;suse&#34;;&#xA;   }&#xA;@@ -625,6 +626,7 @@&#xA;   return StringSwitch(VendorName)&#xA;     .Case(&#34;apple&#34;, Triple::Apple)&#xA;     .Case(&#34;pc&#34;, Triple::PC)&#xA;.Case(&#34;radix&#34;, Triple::Radix)&#xA;     .Case(&#34;scei&#34;, Triple::SCEI)&#xA;     .Case(&#34;sie&#34;, Triple::SCEI)&#xA;     .Case(&#34;fsl&#34;, Triple::Freescale)&#xA;&#xA;Первый файл содержит массивы имен целевых триплетов для различных архитектур CPU, и здесь мы добавили наш триплет в массив codeX8664Triples[]/code.&#xA;&#xA;Остальные два файла необходимо редактировать на случай того, если вы захотите изменять некоторые величины динамически, во время сборки LLVM. Например, в зависимости от имени операционной системы в триплете, выбирать путь к интерпретатору:&#xA;&#xA;  if (Triple.getVendor() == llvm::Triple::Radix ) {&#xA;    LibDir = X32 ? &#34;libx32&#34; : &#34;lib&#34;;&#xA;  } else {&#xA;    LibDir = X32 ? &#34;libx32&#34; : &#34;lib64&#34;;&#xA;  }&#xA;  Loader = X32 ? &#34;ld-linux-x32.so.2&#34; : &#34;ld-linux-x86-64.so.2&#34;;&#xA;&#xA;Здесь переменная Triple.getVendor() содержит текущее имя системы и вы всегда можете сравнивать его с тем именем, для которого необходимо выполнить определенные действия.&#xA;&#xA;Rust Compiler&#xA;&#xA;Итак, мы добавили новый триплет в проект LLVM. Теперь необходимо изменить еще несколько файлов, но уже непосредственно для компилятора Rust:&#xA;&#xA;rust-1.82.0/compiler/rustctarget/src/spec/mod.rs&#xA;rust-1.82.0/library/std/Cargo.toml&#xA;rust-1.82.0/src/bootstrap/src/core/sanity.rs&#xA;&#xA;И кроме того, в каталог rust-1.82.0/compiler/rustctarget/src/spec/targets/, добавить файл описания целевой архитектуры, соотвествующей новому триплету:&#xA;&#xA;x8664radixlinuxgnu.rs:&#xA;&#xA;use crate::spec::{base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target};&#xA;&#xA;pub fn target() -  Target {&#xA;    let mut base = base::linuxgnu::opts();&#xA;    base.cpu = &#34;x86-64&#34;.into();&#xA;    base.pltbydefault = false;&#xA;    base.maxatomicwidth = Some(64);&#xA;    base.addprelinkargs(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &amp;[&#34;-m64&#34;]);&#xA;    base.stackprobes = StackProbeType::Inline;&#xA;    base.staticpositionindependentexecutables = true;&#xA;    base.supportedsanitizers = SanitizerSet::ADDRESS&#xA;        | SanitizerSet::CFI&#xA;        | SanitizerSet::KCFI&#xA;        | SanitizerSet::DATAFLOW&#xA;        | SanitizerSet::LEAK&#xA;        | SanitizerSet::MEMORY&#xA;        | SanitizerSet::SAFESTACK&#xA;        | SanitizerSet::THREAD;&#xA;    base.supportsxray = true;&#xA;&#xA;    // When we&#39;re asked to use the rust-lld linker by default, set the appropriate lld-using&#xA;    // linker flavor, and self-contained linker component.&#xA;    if optionenv!(&#34;CFGUSESELFCONTAINEDLINKER&#34;).issome() {&#xA;        base.linkerflavor = LinkerFlavor::Gnu(Cc::Yes, Lld::Yes);&#xA;        base.linkselfcontained = crate::spec::LinkSelfContainedDefault::withlinker();&#xA;    }&#xA;&#xA;    Target {&#xA;        llvmtarget: &#34;x8664-radix-linux-gnu&#34;.into(),&#xA;        metadata: crate::spec::TargetMetadata {&#xA;            description: Some(&#34;64-bit Linux (kernel 3.2+, glibc 2.17+)&#34;.into()),&#xA;            tier: Some(1),&#xA;            hosttools: Some(true),&#xA;            std: Some(true),&#xA;        },&#xA;        pointerwidth: 64,&#xA;        datalayout:&#xA;            &#34;e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128&#34;.into(),&#xA;        arch: &#34;x8664&#34;.into(),&#xA;        options: base,&#xA;    }&#xA;}&#xA;&#xA;В случае x8664 создание такого файла достаточно просто, его содержимое можно скопировать из файла x8664unknownlinuxgnu.rs и изменить в нем имя триплета на x8664-radix-linux-gnu.&#xA;&#xA;Патч для Rust 1.82.0 представлен на следующем листинге:&#xA;&#xA;diff --unified -Nr rust-1.82.0-orig/compiler/rustctarget/src/spec/mod.rs rust-1.82.0/compiler/rustctarget/src/spec/mod.rs&#xA;--- rust-1.82.0-orig/compiler/rustctarget/src/spec/mod.rs&#x9;2024-11-10 22:28:19.000000000 +0300&#xA;+++ rust-1.82.0/compiler/rustctarget/src/spec/mod.rs&#x9;2024-11-11 01:47:03.927109832 +0300&#xA;@@ -1646,6 +1646,9 @@&#xA; &#xA;     (&#34;i686-unknown-hurd-gnu&#34;, i686unknownhurdgnu),&#xA; &#xA;// RcL Triples:&#xA;(&#34;x8664-radix-linux-gnu&#34;, x8664radixlinuxgnu),&#xA;(&#34;aarch64-apple-darwin&#34;, aarch64appledarwin),&#xA;     (&#34;arm64e-apple-darwin&#34;, arm64eappledarwin),&#xA;     (&#34;x8664-apple-darwin&#34;, x8664appledarwin),&#xA;diff --unified -Nr rust-1.82.0-orig/compiler/rustctarget/src/spec/targets/x8664radixlinuxgnu.rs rust-1.82.0/compiler/rustctarget/src/spec/targets/x8664radixlinuxgnu.rs&#xA;--- rust-1.82.0-orig/compiler/rustctarget/src/spec/targets/x8664radixlinuxgnu.rs&#x9;1970-01-01 03:00:00.000000000 +0300&#xA;+++ rust-1.82.0/compiler/rustctarget/src/spec/targets/x8664radixlinuxgnu.rs&#x9;2024-11-11 01:47:03.927109832 +0300&#xA;@@ -0,0 +1,42 @@&#xA;+use crate::spec::{base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target};&#xA;+pub fn target() -  Target {&#xA;let mut base = base::linuxgnu::opts();&#xA;base.cpu = &#34;x86-64&#34;.into();&#xA;base.pltbydefault = false;&#xA;base.maxatomicwidth = Some(64);&#xA;base.addprelinkargs(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &amp;[&#34;-m64&#34;]);&#xA;base.stackprobes = StackProbeType::Inline;&#xA;base.staticpositionindependentexecutables = true;&#xA;base.supportedsanitizers = SanitizerSet::ADDRESS&#xA;| SanitizerSet::CFI&#xA;| SanitizerSet::KCFI&#xA;| SanitizerSet::DATAFLOW&#xA;| SanitizerSet::LEAK&#xA;| SanitizerSet::MEMORY&#xA;| SanitizerSet::SAFESTACK&#xA;| SanitizerSet::THREAD;&#xA;base.supportsxray = true;&#xA;// When we&#39;re asked to use the rust-lld linker by default, set the appropriate lld-using&#xA;// linker flavor, and self-contained linker component.&#xA;if optionenv!(&#34;CFGUSESELFCONTAINEDLINKER&#34;).issome() {&#xA;base.linkerflavor = LinkerFlavor::Gnu(Cc::Yes, Lld::Yes);&#xA;base.linkselfcontained = crate::spec::LinkSelfContainedDefault::withlinker();&#xA;}&#xA;Target {&#xA;llvmtarget: &#34;x8664-radix-linux-gnu&#34;.into(),&#xA;metadata: crate::spec::TargetMetadata {&#xA;description: Some(&#34;64-bit Linux (kernel 3.2+, glibc 2.17+)&#34;.into()),&#xA;tier: Some(1),&#xA;hosttools: Some(true),&#xA;std: Some(true),&#xA;},&#xA;pointerwidth: 64,&#xA;datalayout:&#xA;&#34;e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128&#34;.into(),&#xA;arch: &#34;x8664&#34;.into(),&#xA;options: base,&#xA;}&#xA;+}&#xA;diff --unified -Nr rust-1.82.0-orig/library/std/Cargo.toml rust-1.82.0/library/std/Cargo.toml&#xA;--- rust-1.82.0-orig/library/std/Cargo.toml&#x9;2024-11-10 22:28:19.000000000 +0300&#xA;+++ rust-1.82.0/library/std/Cargo.toml&#x9;2024-11-11 01:47:03.927109832 +0300&#xA;@@ -141,7 +141,7 @@&#xA; level = &#34;warn&#34;&#xA; check-cfg = [&#xA;     &#39;cfg(bootstrap)&#39;,&#xA;&#39;cfg(targetarch, values(&#34;xtensa&#34;))&#39;,&#xA;&#39;cfg(targetarch, values(&#34;xtensa&#34;, &#34;x8664-radix-linux-gnu&#34;))&#39;,&#xA;     # std use #[path] imports to portable-simd stdfloat crate&#xA;     # and to the backtrace crate which messes-up with Cargo list&#xA;     # of declared features, we therefor expect any feature cfg&#xA;diff --unified -Nr rust-1.82.0-orig/src/bootstrap/src/core/sanity.rs rust-1.82.0/src/bootstrap/src/core/sanity.rs&#xA;--- rust-1.82.0-orig/src/bootstrap/src/core/sanity.rs&#x9;2024-11-10 22:28:19.000000000 +0300&#xA;+++ rust-1.82.0/src/bootstrap/src/core/sanity.rs&#x9;2024-11-11 01:47:03.927109832 +0300&#xA;@@ -34,6 +34,7 @@&#xA; // Targets can be removed from this list once they are present in the stage0 compiler (usually by updating the beta compiler of the bootstrap).&#xA; const STAGE0MISSINGTARGETS: &amp;[&amp;str] = &amp;[&#xA;     // just a dummy comment so the list doesn&#39;t get onelined&#xA;&#34;x8664-radix-linux-gnu&#34;&#xA; ];&#xA; &#xA; /// Minimum version threshold for libstdc++ required when using prebuilt LLVM&#xA;&#xA;Make and Install&#xA;&#xA;Теперь мы готовы к сборке Rust инструментария.&#xA;&#xA;Сконфигурировать исходный код Rust можно с помощью следующей команды:&#xA;&#xA;./configure --prefix=/opt/toolchains/RUST/1.82.0 \&#xA;            --sysconfdir=/opt/toolchains/RUST/1.82.0/etc \&#xA;            --disable-codegen-tests \&#xA;            --disable-vendor \&#xA;            --build=x8664-unknown-linux-gnu \&#xA;            --host=x8664-unknown-linux-gnu \&#xA;            --target=x8664-unknown-linux-gnu,x8664-radix-linux-gnu \&#xA;            --enable-clang&#xA;&#xA;Здесь мы выбрали стандартный целевой триплет для архитектуры x8664, а также наш новый триплет x8664-radix-linux-gnu.&#xA;&#xA;После выполнения данной команды, будет создан файл config.toml следующего содержания:&#xA;&#xA;profile = &#39;dist&#39;&#xA;change-id = 129295&#xA;&#xA;[llvm]&#xA;clang = true&#xA;&#xA;[build]&#xA;build = &#39;x8664-unknown-linux-gnu&#39;&#xA;host = [&#39;x8664-unknown-linux-gnu&#39;]&#xA;target = [&#39;x8664-unknown-linux-gnu&#39;, &#39;x8664-radix-linux-gnu&#39;]&#xA;vendor = false&#xA;configure-args = [&#39;--prefix=/opt/toolchains/RUST/1.82.0&#39;, &#39;--sysconfdir=/opt/toolchains/RUST/1.82.0/etc&#39;, &#39;--disable-codegen-tests&#39;, &#39;--disable-vendor&#39;, &#39;--build=x8664-unknown-linux-gnu&#39;, &#39;--host=x8664-unknown-linux-gnu&#39;, &#39;--target=x8664-unknown-linux-gnu,x8664-radix-linux-gnu&#39;, &#39;--enable-clang&#39;]&#xA;&#xA;[install]&#xA;prefix = &#39;/opt/toolchains/RUST/1.82.0&#39;&#xA;sysconfdir = &#39;/opt/toolchains/RUST/1.82.0/etc&#39;&#xA;&#xA;[rust]&#xA;codegen-tests = false&#xA;&#xA;[target.x8664-unknown-linux-gnu]&#xA;&#xA;[target.x8664-radix-linux-gnu]&#xA;&#xA;[dist]&#xA;&#xA;Этот файл также необходимо отредактировать, добавив идентификатор изменений:&#xA;&#xA;change-id = 129295&#xA;&#xA;Его можно легко получить попробовав команду make, которая приведет к неудаче, но выведет на экран необходимый идентификатор. Вообще, правильный путь поиска величины change-id состоит в том, чтобы посмотреть последнюю запись ChangeInfo в файле:&#xA;&#xA;rust-1.82.0/src/bootstrap/src/utils/changetracker.rs&#xA;&#xA;В приведенном выше файле config.toml мы уже сделали эти изменения.&#xA;&#xA;В нашем случае, секцию [target.x8664-radix-linux-gnu] изменять нет необходимости. Однако если вы захотите создать триплет для другой архитектуры, требующей cross-сборки, то вам будет необходимо собрать GCC-toolchain и добавить в соответствующую секцию сведения об основных утилитах, например, так:&#xA;&#xA;[target.aarch64-m1000-linux-gnu]&#xA;linker = &#39;/opt/toolchains/aarch64-M1000-linux-glibc/1.11.3/bin/aarch64-m1000-linux-gnu-gcc&#39;&#xA;cc = &#39;/opt/toolchains/aarch64-M1000-linux-glibc/1.11.3/bin/aarch64-m1000-linux-gnu-gcc&#39;&#xA;cxx = &#39;/opt/toolchains/aarch64-M1000-linux-glibc/1.11.3/bin/aarch64-m1000-linux-gnu-g++&#39;&#xA;ar = &#39;/opt/toolchains/aarch64-M1000-linux-glibc/1.11.3/bin/aarch64-m1000-linux-gnu-ar&#39;&#xA;ranlib = &#39;/opt/toolchains/aarch64-M1000-linux-glibc/1.11.3/bin/aarch64-m1000-linux-gnu-ranlib&#39;&#xA;&#xA;Здесь мы не будем рассматривать тонкости создания cross-компилятора Rust.&#xA;&#xA;После того, как исходный код Rust сконфигурирован, собрать и инсталлировать компилятор можно с помощью следующих команд:&#xA;&#xA;make&#xA;make install&#xA;&#xA;Далее необходимо инсталлировать утилиту cbindgen:&#xA;&#xA;export PATH=/opt/toolchains/RUST/1.82.0/bin:$PATH&#xA;cargo  install --root /opt/toolchains/RUST/1.82.0 --version 0.27.0 cbindgen&#xA;&#xA;Теперь Rust инструментарий готов к работе.&#xA;&#xA;Если вы уже инсталлировали cargo в домашний каталог, то вы можете подключить собранный вами инструментарий (toolchain) в набор уже инсталлированых ранее toolchain-ов, например, с именем RcL-1.82.0-x8664-unknown :&#xA;&#xA;bash-5.1$ rustup toolchain link RcL-1.82.0-x8664-unknown-linux-gnu /opt/toolchains/RUST/1.82.0&#xA;&#xA;По завершении данной команды, список ваших toolchain-ов может выглядеть, например, так:&#xA;&#xA;bash-5.1$ rustup toolchain list&#xA;&#xA;stable-x8664-unknown-linux-gnu&#xA;RcL-1.82.0-x8664-unknown-linux-gnu&#xA;1.71.1-x8664-unknown-linux-gnu (default)&#xA;&#xA;Итак, в отличие от GNU Коллекции Компиляторов, проекты LLVM и Rust построены так, что элементарные настройки превращаются в достаточно нетривиальную последовательность действий. А ведь все начиналось весьма просто, но в какой-то момент в очередной выпуск доступных cross-компиляторов Rust (после версии 1.71.1) забыли добавить триплет mipsel-unknown-linux-gnu. Тогда-то и пришлось задуматься о сборке собственных кросс-инструментариев Rust, чтобы обрести некоторую независимость, ведь сейчас все больше и больше открытых проектов выбирают язык Rust.&#xA;&#xA;Enjoy.&#xA;&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>Целевые триплеты описывают платформу, на которой выполняется код, и являются основной концепцией системы сборки GNU. Обычно триплет содержит три поля: название семейства/модели CPU, поставщика и имя операционной системы. Кроме того, триплет может иметь дополнительное поле, отражающее Application Binary Interface (ABI), например: gnu, gnueabihf, gnu_ilp32.</p>

<p><img src="https://radix-linux.su/blog/2024-11-11/00/.pixmaps/rust-1024x576.png" alt="Rust Custom Triplet"></p>

<p>Просмотреть целевой триплет текущей системы можно с помощью команды `gcc -dumpmachine&#39;:</p>

<pre><code class="language-sh">bash-5.1$ gcc -dumpmachine
x86_64-slackware-linux
</code></pre>

<p>Если вы создаете новую систему или собственный GNU/Linux дистрибутив, у вас может возникнуть необходимость иметь собственный целевой триплет. Например, x86_64-radix-linux-gnu для CPU Intel или AMD.</p>

<p>При создании инструментария (toolchain-а) на базе GCC все выглядит элементарно. Достаточно сконфигурировать binutils с опцией —enable-targets=x86_64-radix-linux-gnu. Однако добавление собственного триплета компиляторов LLVM и Rust выглядит уже не совсем тривиально.</p>

<p>Здесь мы рассмотрим добавление нового триплета инструментария языка Rust.</p>

<p>Прежде всего необходимо загрузить исходный код:</p>

<pre><code class="language-sh">git clone https://github.com/rust-lang/rust.git rust-1.82.0
( cd rust-1.82.0
  git checkout -b 1.82.0 tags/1.82.0
  git submodule update --init --recursive )
</code></pre>

<p>Поскольку репозиторий исходного кода Rust содержит исходный код проекта LLVM, мы сможем одновременно рассмотреть добавление нового триплета и для случая LLVM, и для случая Rust.</p>

<h2 id="llvm-project">LLVM Project</h2>

<p>Итак, для того чтобы добавить новый триплет компилятору clang нам необходимо внести изменения в файлы:</p>

<pre><code class="language-sh">rust-1.82.0/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp
rust-1.82.0/src/llvm-project/llvm/include/llvm/TargetParser/Triple.h
rust-1.82.0/src/llvm-project/llvm/lib/TargetParser/Triple.cpp
</code></pre>

<p>Патч для Rust 1.82.0 представлен на следующем листинге:</p>

<pre><code class="language-diff">diff --unified -Nr rust-1.82.0-orig/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp rust-1.82.0/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp
--- rust-1.82.0-orig/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp	2024-11-10 22:33:14.000000000 +0300
+++ rust-1.82.0/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp	2024-11-11 01:34:23.586151730 +0300
@@ -2491,7 +2491,7 @@
       &#34;x86_64-linux-gnu&#34;,       &#34;x86_64-unknown-linux-gnu&#34;,
       &#34;x86_64-pc-linux-gnu&#34;,    &#34;x86_64-redhat-linux6E&#34;,
       &#34;x86_64-redhat-linux&#34;,    &#34;x86_64-suse-linux&#34;,
-      &#34;x86_64-manbo-linux-gnu&#34;, &#34;x86_64-slackware-linux&#34;,
+      &#34;x86_64-manbo-linux-gnu&#34;, &#34;x86_64-slackware-linux&#34;, &#34;x86_64-radix-linux-gnu&#34;,
       &#34;x86_64-unknown-linux&#34;,   &#34;x86_64-amazon-linux&#34;};
   static const char *const X32Triples[] = {&#34;x86_64-linux-gnux32&#34;,
                                            &#34;x86_64-pc-linux-gnux32&#34;};
diff --unified -Nr rust-1.82.0-orig/src/llvm-project/llvm/include/llvm/TargetParser/Triple.h rust-1.82.0/src/llvm-project/llvm/include/llvm/TargetParser/Triple.h
--- rust-1.82.0-orig/src/llvm-project/llvm/include/llvm/TargetParser/Triple.h	2024-11-10 22:33:17.000000000 +0300
+++ rust-1.82.0/src/llvm-project/llvm/include/llvm/TargetParser/Triple.h	2024-11-11 01:34:23.585151730 +0300
@@ -183,6 +183,7 @@
 
     Apple,
     PC,
+    Radix,
     SCEI,
     Freescale,
     IBM,
diff --unified -Nr rust-1.82.0-orig/src/llvm-project/llvm/lib/TargetParser/Triple.cpp rust-1.82.0/src/llvm-project/llvm/lib/TargetParser/Triple.cpp
--- rust-1.82.0-orig/src/llvm-project/llvm/lib/TargetParser/Triple.cpp	2024-11-10 22:33:17.000000000 +0300
+++ rust-1.82.0/src/llvm-project/llvm/lib/TargetParser/Triple.cpp	2024-11-11 01:34:23.585151730 +0300
@@ -251,6 +251,7 @@
   case NVIDIA: return &#34;nvidia&#34;;
   case OpenEmbedded: return &#34;oe&#34;;
   case PC: return &#34;pc&#34;;
+  case Radix: return &#34;radix&#34;;
   case SCEI: return &#34;scei&#34;;
   case SUSE: return &#34;suse&#34;;
   }
@@ -625,6 +626,7 @@
   return StringSwitch(VendorName)
     .Case(&#34;apple&#34;, Triple::Apple)
     .Case(&#34;pc&#34;, Triple::PC)
+    .Case(&#34;radix&#34;, Triple::Radix)
     .Case(&#34;scei&#34;, Triple::SCEI)
     .Case(&#34;sie&#34;, Triple::SCEI)
     .Case(&#34;fsl&#34;, Triple::Freescale)
</code></pre>

<p>Первый файл содержит массивы имен целевых триплетов для различных архитектур CPU, и здесь мы добавили наш триплет в массив <code>X86_64Triples[]</code>.</p>

<p>Остальные два файла необходимо редактировать на случай того, если вы захотите изменять некоторые величины динамически, во время сборки LLVM. Например, в зависимости от имени операционной системы в триплете, выбирать путь к интерпретатору:</p>

<pre><code class="language-c++">  if (Triple.getVendor() == llvm::Triple::Radix ) {
    LibDir = X32 ? &#34;libx32&#34; : &#34;lib&#34;;
  } else {
    LibDir = X32 ? &#34;libx32&#34; : &#34;lib64&#34;;
  }
  Loader = X32 ? &#34;ld-linux-x32.so.2&#34; : &#34;ld-linux-x86-64.so.2&#34;;
</code></pre>

<p>Здесь переменная Triple.getVendor() содержит текущее имя системы и вы всегда можете сравнивать его с тем именем, для которого необходимо выполнить определенные действия.</p>

<h2 id="rust-compiler">Rust Compiler</h2>

<p>Итак, мы добавили новый триплет в проект LLVM. Теперь необходимо изменить еще несколько файлов, но уже непосредственно для компилятора Rust:</p>

<pre><code class="language-sh">rust-1.82.0/compiler/rustc_target/src/spec/mod.rs
rust-1.82.0/library/std/Cargo.toml
rust-1.82.0/src/bootstrap/src/core/sanity.rs
</code></pre>

<p>И кроме того, в каталог rust-1.82.0/compiler/rustc_target/src/spec/targets/, добавить файл описания целевой архитектуры, соотвествующей новому триплету:</p>

<h3 id="x86-64-radix-linux-gnu-rs">x86<em>64</em>radix<em>linux</em>gnu.rs:</h3>

<pre><code class="language-rust">use crate::spec::{base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target};

pub fn target() -&gt; Target {
    let mut base = base::linux_gnu::opts();
    base.cpu = &#34;x86-64&#34;.into();
    base.plt_by_default = false;
    base.max_atomic_width = Some(64);
    base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &amp;[&#34;-m64&#34;]);
    base.stack_probes = StackProbeType::Inline;
    base.static_position_independent_executables = true;
    base.supported_sanitizers = SanitizerSet::ADDRESS
        | SanitizerSet::CFI
        | SanitizerSet::KCFI
        | SanitizerSet::DATAFLOW
        | SanitizerSet::LEAK
        | SanitizerSet::MEMORY
        | SanitizerSet::SAFESTACK
        | SanitizerSet::THREAD;
    base.supports_xray = true;

    // When we&#39;re asked to use the `rust-lld` linker by default, set the appropriate lld-using
    // linker flavor, and self-contained linker component.
    if option_env!(&#34;CFG_USE_SELF_CONTAINED_LINKER&#34;).is_some() {
        base.linker_flavor = LinkerFlavor::Gnu(Cc::Yes, Lld::Yes);
        base.link_self_contained = crate::spec::LinkSelfContainedDefault::with_linker();
    }

    Target {
        llvm_target: &#34;x86_64-radix-linux-gnu&#34;.into(),
        metadata: crate::spec::TargetMetadata {
            description: Some(&#34;64-bit Linux (kernel 3.2+, glibc 2.17+)&#34;.into()),
            tier: Some(1),
            host_tools: Some(true),
            std: Some(true),
        },
        pointer_width: 64,
        data_layout:
            &#34;e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128&#34;.into(),
        arch: &#34;x86_64&#34;.into(),
        options: base,
    }
}
</code></pre>

<p>В случае x86<em>64 создание такого файла достаточно просто, его содержимое можно скопировать из файла x86</em>64<em>unknown</em>linux<em>gnu.rs и изменить в нем имя триплета на x86</em>64-radix-linux-gnu.</p>

<p>Патч для Rust 1.82.0 представлен на следующем листинге:</p>

<pre><code class="language-diff">diff --unified -Nr rust-1.82.0-orig/compiler/rustc_target/src/spec/mod.rs rust-1.82.0/compiler/rustc_target/src/spec/mod.rs
--- rust-1.82.0-orig/compiler/rustc_target/src/spec/mod.rs	2024-11-10 22:28:19.000000000 +0300
+++ rust-1.82.0/compiler/rustc_target/src/spec/mod.rs	2024-11-11 01:47:03.927109832 +0300
@@ -1646,6 +1646,9 @@
 
     (&#34;i686-unknown-hurd-gnu&#34;, i686_unknown_hurd_gnu),
 
+    // RcL Triples:
+    (&#34;x86_64-radix-linux-gnu&#34;, x86_64_radix_linux_gnu),
+
     (&#34;aarch64-apple-darwin&#34;, aarch64_apple_darwin),
     (&#34;arm64e-apple-darwin&#34;, arm64e_apple_darwin),
     (&#34;x86_64-apple-darwin&#34;, x86_64_apple_darwin),
diff --unified -Nr rust-1.82.0-orig/compiler/rustc_target/src/spec/targets/x86_64_radix_linux_gnu.rs rust-1.82.0/compiler/rustc_target/src/spec/targets/x86_64_radix_linux_gnu.rs
--- rust-1.82.0-orig/compiler/rustc_target/src/spec/targets/x86_64_radix_linux_gnu.rs	1970-01-01 03:00:00.000000000 +0300
+++ rust-1.82.0/compiler/rustc_target/src/spec/targets/x86_64_radix_linux_gnu.rs	2024-11-11 01:47:03.927109832 +0300
@@ -0,0 +1,42 @@
+use crate::spec::{base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target};
+
+pub fn target() -&gt; Target {
+    let mut base = base::linux_gnu::opts();
+    base.cpu = &#34;x86-64&#34;.into();
+    base.plt_by_default = false;
+    base.max_atomic_width = Some(64);
+    base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &amp;[&#34;-m64&#34;]);
+    base.stack_probes = StackProbeType::Inline;
+    base.static_position_independent_executables = true;
+    base.supported_sanitizers = SanitizerSet::ADDRESS
+        | SanitizerSet::CFI
+        | SanitizerSet::KCFI
+        | SanitizerSet::DATAFLOW
+        | SanitizerSet::LEAK
+        | SanitizerSet::MEMORY
+        | SanitizerSet::SAFESTACK
+        | SanitizerSet::THREAD;
+    base.supports_xray = true;
+
+    // When we&#39;re asked to use the `rust-lld` linker by default, set the appropriate lld-using
+    // linker flavor, and self-contained linker component.
+    if option_env!(&#34;CFG_USE_SELF_CONTAINED_LINKER&#34;).is_some() {
+        base.linker_flavor = LinkerFlavor::Gnu(Cc::Yes, Lld::Yes);
+        base.link_self_contained = crate::spec::LinkSelfContainedDefault::with_linker();
+    }
+
+    Target {
+        llvm_target: &#34;x86_64-radix-linux-gnu&#34;.into(),
+        metadata: crate::spec::TargetMetadata {
+            description: Some(&#34;64-bit Linux (kernel 3.2+, glibc 2.17+)&#34;.into()),
+            tier: Some(1),
+            host_tools: Some(true),
+            std: Some(true),
+        },
+        pointer_width: 64,
+        data_layout:
+            &#34;e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128&#34;.into(),
+        arch: &#34;x86_64&#34;.into(),
+        options: base,
+    }
+}
diff --unified -Nr rust-1.82.0-orig/library/std/Cargo.toml rust-1.82.0/library/std/Cargo.toml
--- rust-1.82.0-orig/library/std/Cargo.toml	2024-11-10 22:28:19.000000000 +0300
+++ rust-1.82.0/library/std/Cargo.toml	2024-11-11 01:47:03.927109832 +0300
@@ -141,7 +141,7 @@
 level = &#34;warn&#34;
 check-cfg = [
     &#39;cfg(bootstrap)&#39;,
-    &#39;cfg(target_arch, values(&#34;xtensa&#34;))&#39;,
+    &#39;cfg(target_arch, values(&#34;xtensa&#34;, &#34;x86_64-radix-linux-gnu&#34;))&#39;,
     # std use #[path] imports to portable-simd `std_float` crate
     # and to the `backtrace` crate which messes-up with Cargo list
     # of declared features, we therefor expect any feature cfg
diff --unified -Nr rust-1.82.0-orig/src/bootstrap/src/core/sanity.rs rust-1.82.0/src/bootstrap/src/core/sanity.rs
--- rust-1.82.0-orig/src/bootstrap/src/core/sanity.rs	2024-11-10 22:28:19.000000000 +0300
+++ rust-1.82.0/src/bootstrap/src/core/sanity.rs	2024-11-11 01:47:03.927109832 +0300
@@ -34,6 +34,7 @@
 // Targets can be removed from this list once they are present in the stage0 compiler (usually by updating the beta compiler of the bootstrap).
 const STAGE0_MISSING_TARGETS: &amp;[&amp;str] = &amp;[
     // just a dummy comment so the list doesn&#39;t get onelined
+    &#34;x86_64-radix-linux-gnu&#34;
 ];
 
 /// Minimum version threshold for libstdc++ required when using prebuilt LLVM
</code></pre>

<h2 id="make-and-install">Make and Install</h2>

<p>Теперь мы готовы к сборке Rust инструментария.</p>

<p>Сконфигурировать исходный код Rust можно с помощью следующей команды:</p>

<pre><code class="language-sh">./configure --prefix=/opt/toolchains/RUST/1.82.0 \
            --sysconfdir=/opt/toolchains/RUST/1.82.0/etc \
            --disable-codegen-tests \
            --disable-vendor \
            --build=x86_64-unknown-linux-gnu \
            --host=x86_64-unknown-linux-gnu \
            --target=x86_64-unknown-linux-gnu,x86_64-radix-linux-gnu \
            --enable-clang
</code></pre>

<p>Здесь мы выбрали стандартный целевой триплет для архитектуры x86<em>64, а также наш новый триплет x86</em>64-radix-linux-gnu.</p>

<p>После выполнения данной команды, будет создан файл config.toml следующего содержания:</p>

<pre><code class="language-ini">profile = &#39;dist&#39;
change-id = 129295

[llvm]
clang = true

[build]
build = &#39;x86_64-unknown-linux-gnu&#39;
host = [&#39;x86_64-unknown-linux-gnu&#39;]
target = [&#39;x86_64-unknown-linux-gnu&#39;, &#39;x86_64-radix-linux-gnu&#39;]
vendor = false
configure-args = [&#39;--prefix=/opt/toolchains/RUST/1.82.0&#39;, &#39;--sysconfdir=/opt/toolchains/RUST/1.82.0/etc&#39;, &#39;--disable-codegen-tests&#39;, &#39;--disable-vendor&#39;, &#39;--build=x86_64-unknown-linux-gnu&#39;, &#39;--host=x86_64-unknown-linux-gnu&#39;, &#39;--target=x86_64-unknown-linux-gnu,x86_64-radix-linux-gnu&#39;, &#39;--enable-clang&#39;]

[install]
prefix = &#39;/opt/toolchains/RUST/1.82.0&#39;
sysconfdir = &#39;/opt/toolchains/RUST/1.82.0/etc&#39;

[rust]
codegen-tests = false

[target.x86_64-unknown-linux-gnu]

[target.x86_64-radix-linux-gnu]

[dist]
</code></pre>

<p>Этот файл также необходимо отредактировать, добавив идентификатор изменений:</p>

<pre><code class="language-ini">change-id = 129295
</code></pre>

<p>Его можно легко получить попробовав команду make, которая приведет к неудаче, но выведет на экран необходимый идентификатор. Вообще, правильный путь поиска величины change-id состоит в том, чтобы посмотреть последнюю запись ChangeInfo в файле:</p>

<pre><code class="language-sh">rust-1.82.0/src/bootstrap/src/utils/change_tracker.rs
</code></pre>

<p>В приведенном выше файле config.toml мы уже сделали эти изменения.</p>

<p>В нашем случае, секцию [target.x86_64-radix-linux-gnu] изменять нет необходимости. Однако если вы захотите создать триплет для другой архитектуры, требующей cross-сборки, то вам будет необходимо собрать GCC-toolchain и добавить в соответствующую секцию сведения об основных утилитах, например, так:</p>

<pre><code class="language-ini">[target.aarch64-m1000-linux-gnu]
linker = &#39;/opt/toolchains/aarch64-M1000-linux-glibc/1.11.3/bin/aarch64-m1000-linux-gnu-gcc&#39;
cc = &#39;/opt/toolchains/aarch64-M1000-linux-glibc/1.11.3/bin/aarch64-m1000-linux-gnu-gcc&#39;
cxx = &#39;/opt/toolchains/aarch64-M1000-linux-glibc/1.11.3/bin/aarch64-m1000-linux-gnu-g++&#39;
ar = &#39;/opt/toolchains/aarch64-M1000-linux-glibc/1.11.3/bin/aarch64-m1000-linux-gnu-ar&#39;
ranlib = &#39;/opt/toolchains/aarch64-M1000-linux-glibc/1.11.3/bin/aarch64-m1000-linux-gnu-ranlib&#39;
</code></pre>

<p>Здесь мы не будем рассматривать тонкости создания cross-компилятора Rust.</p>

<p>После того, как исходный код Rust сконфигурирован, собрать и инсталлировать компилятор можно с помощью следующих команд:</p>

<pre><code class="language-sh">make
make install
</code></pre>

<p>Далее необходимо инсталлировать утилиту cbindgen:</p>

<pre><code class="language-sh">export PATH=/opt/toolchains/RUST/1.82.0/bin:$PATH
cargo  install --root /opt/toolchains/RUST/1.82.0 --version 0.27.0 cbindgen
</code></pre>

<p>Теперь Rust инструментарий готов к работе.</p>

<p>Если вы уже инсталлировали cargo в домашний каталог, то вы можете подключить собранный вами инструментарий (toolchain) в набор уже инсталлированых ранее toolchain-ов, например, с именем RcL-1.82.0-x86_64-unknown :</p>

<pre><code class="language-sh">bash-5.1$ rustup toolchain link RcL-1.82.0-x86_64-unknown-linux-gnu /opt/toolchains/RUST/1.82.0
</code></pre>

<p>По завершении данной команды, список ваших toolchain-ов может выглядеть, например, так:</p>

<pre><code class="language-sh">bash-5.1$ rustup toolchain list

stable-x86_64-unknown-linux-gnu
RcL-1.82.0-x86_64-unknown-linux-gnu
1.71.1-x86_64-unknown-linux-gnu (default)
</code></pre>

<p>Итак, в отличие от GNU Коллекции Компиляторов, проекты LLVM и Rust построены так, что элементарные настройки превращаются в достаточно нетривиальную последовательность действий. А ведь все начиналось весьма просто, но в какой-то момент в очередной выпуск доступных cross-компиляторов Rust (после версии 1.71.1) забыли добавить триплет mipsel-unknown-linux-gnu. Тогда-то и пришлось задуматься о сборке собственных кросс-инструментариев Rust, чтобы обрести некоторую независимость, ведь сейчас все больше и больше открытых проектов выбирают язык Rust.</p>

<p><strong>Enjoy.</strong></p>
]]></content:encoded>
      <guid>https://wf.fosstodon.su/kx/rust-custom-triplet</guid>
      <pubDate>Thu, 31 Jul 2025 12:55:49 +0300</pubDate>
    </item>
  </channel>
</rss>