Как я могу запросить rustc для тройного хоста?

#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.

Вот несколько предостережений, о которых следует помнить при использовании этой команды:

  1. Для этой команды требуется bash, потому что я использую <(..) конструкцию. Эта команда может быть изменена для использования явных временных файлов за счет большей сложности.
  2. Эта команда создаст более одной целевой тройки, если компилятор попытается получить доступ к файлам для платформ, отличных от хоста. Это сделано намеренно. Если это проблема, вы можете использовать эвристический подход, используя uniq --count ), sort и head , чтобы выбрать наиболее доступную тройку.
  3. Регулярное выражение, используемое для фильтрации троек, не такое жесткое, как мне бы хотелось. Вероятно, его можно сузить гораздо больше, если тройки будут придерживаться формальной спецификации. Я обновлю позже, если мне удастся выкроить немного времени.

Приветствия!

Комментарии:

1. Обратите внимание, что вы можете получить каталог с помощью rustc --print sysroot , so basename $(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);
}