#rust #cross-compiling #triplet
#Ржавчина #кросс-компиляция #триплет #перекрестная компиляция #тройной
Вопрос:
При работе с gcc я могу получить то, что gcc считает триплетом моего хоста, запустив gcc -dumpmachine
. В моей нынешней системе это дает мне x86_64-linux-gnu
.
Как я могу добиться стабильности rustc
для печати моего хоста triple? ( x86_64-unknown-linux-gnu
в данном случае)
rustc
документация, похоже, не содержит ничего значимого, кроме --print
и --version
. Ни то, ни другое, похоже, не приводит к утроению целевого хоста.
Уточнение: учитывая, что пока было дано два ответа о nightly, я хочу подчеркнуть, что этот вопрос конкретно касается стабильных rustc
компиляторов.
Комментарии:
1. GCC в значительной степени является создателем обозначения триплетов, так что просто обратитесь к нему. Rust просто использует ту же нотацию, чтобы уменьшить путаницу, хотя я согласен, было бы здорово иметь эту функцию в
rustc
2. Итак, нет способа получить тройной хост из
rustc
? Я пытаюсь избежать сохранения рукописного сопоставления троек, если я могу этого избежать.3. Вы можете взять триплетный вывод
gcc
через bash и заменить его в команде сборки
Ответ №1:
rustc --version --verbose
Даст вам некоторый вывод, подобный:
rustc 1.35.0-nightly (474e7a648 2019-04-07)
binary: rustc
commit-hash: 474e7a6486758ea6fc761893b1a49cd9076fb0ab
commit-date: 2019-04-07
host: x86_64-unknown-linux-gnu
release: 1.35.0-nightly
LLVM version: 8.0
Где хост является вашей целевой тройкой.
Комментарии:
1. Привет, Тейлор, и добро пожаловать в SO. К сожалению, rustc не показывает целевую тройку в стабильном режиме. Отображается только первая строка
rustc 1.46.0 (04488afe3 2020-08-24)
.2. (Откуда-то перепечатано) Если у вас есть awk:
rustc -vV | awk '/^host/ { print $2 }'
3. Похоже, что теперь это работает стабильно. Принимаю ответ.
Ответ №2:
С помощью Rust nightly вы можете распечатать «целевую спецификацию JSON»:
$ rustc nightly -Z unstable-options --print target-spec-json
{
"arch": "x86_64",
"cpu": "x86-64",
"data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128",
"dynamic-linking": true,
"env": "gnu",
"executables": true,
"has-elf-tls": true,
"has-rpath": true,
"is-builtin": true,
"linker-flavor": "gcc",
"linker-is-gnu": true,
"llvm-target": "x86_64-unknown-linux-gnu",
"max-atomic-width": 64,
"os": "linux",
"position-independent-executables": true,
"pre-link-args": {
"gcc": [
"-Wl,--as-needed",
"-Wl,-z,noexecstack",
"-m64"
]
},
"relro-level": "full",
"stack-probes": true,
"target-c-int-width": "32",
"target-endian": "little",
"target-family": "unix",
"target-pointer-width": "64",
"vendor": "unknown"
}
Чтобы проанализировать целевую тройку из этого в командной строке, вы могли бы использовать такой инструмент, как jq
:
$ rustc nightly -Z unstable-options --print target-spec-json | jq -r '."llvm-target"'
x86_64-unknown-linux-gnu
Это пока не стабильно (и поэтому требует -Z unstable-options
опции компилятора), но, вероятно, это будет в будущем. Эта функция была добавлена в #38061.
Комментарии:
1. Спасибо. Я решил спросить здесь, потому что увидел, что
target-spec-json
был нестабилен. Вы правы в том, что этот ответ будет правильным, когда, или, возможно, если , он стабилизируется. Я оставлю этот вопрос открытым и приму ваш ответ, как только флаг стабилизируется.2.
llvm-target
может отличаться от того, чтоrustc
рассматривает «хост», и нет никакой гарантии, что это допустимая цель для rustc, верно? В большинстве случаев так и будет, но не обязательно во всех?3. @Max правильно, использование llvm-target ненадежно . Моя целевая тройка rustc — это
aarch64-apple-darwin
но цель llvm — этоarm64-apple-macosx11.0.0
. Ответ Тейлора работает для меня.
Ответ №3:
rustc
(начиная с версии 1.45.2), похоже, не предлагает никакого способа получения тройного целевого хоста.
В качестве обходного пути я решил использовать strace
и небольшую фиктивную программу, чтобы обмануть компилятор, чтобы показать тройной хост; rustc
хранит предварительно скомпилированные библиотеки в отдельных каталогах на основе их тройной платформы.
Вот что у меня получилось:
strace -f -e trace=file rustc <(echo "fn main(){};") 2>amp;1 |
grep -E "(libstd-.*.rlib)|(libcore-.*.rlib)" |
sed -E "s:^.*"/.*/([^/] -[^/] (-[/^] (-[^/] )?)?)/.*".*$:1:g;t;d" |
sort | uniq
Это работает, как и следовало ожидать, x86_64-unknown-linux-gnu
с gnu
установкой ABI rust в 64-разрядной системе Linux.
Теоретически это должно работать с любой версией rustc. Я могу подтвердить, что он работает с rustc 1.43.0 (поставляется с Ubuntu 18.04) и 1.45.2.
Вот несколько предостережений, о которых следует помнить при использовании этой команды:
- Для этой команды требуется bash, потому что я использую
<(..)
конструкцию. Эта команда может быть изменена для использования явных временных файлов за счет большей сложности. - Эта команда создаст более одной целевой тройки, если компилятор попытается получить доступ к файлам для платформ, отличных от хоста. Это сделано намеренно. Если это проблема, вы можете использовать эвристический подход, используя
uniq
(с--count
),sort
иhead
, чтобы выбрать наиболее доступную тройку. - Регулярное выражение, используемое для фильтрации троек, не такое жесткое, как мне бы хотелось. Вероятно, его можно сузить гораздо больше, если тройки будут придерживаться формальной спецификации. Я обновлю позже, если мне удастся выкроить немного времени.
Приветствия!
Комментарии:
1. Обратите внимание, что вы можете получить каталог с помощью
rustc --print sysroot
, sobasename $(rustc --print sysroot)
даст вам тройной
Ответ №4:
Я написал rustc_host
ящик, который позволяет это делать!
Пример:
extern crate rustc_host;
fn main() {
let host_triple = rustc_host::from_cli()
.expect("failed to get host triple from rustc");
println!("host triple: {}", host_triple);
}