Как решить, почему ссылки на cargo / rustc в символах стандартной библиотеки ржавчины, даже когда используется no_std? - PullRequest
0 голосов
/ 12 февраля 2019

Я пытаюсь создать дружественный для встраивания исполняемый файл (небольшой размер и не зависящий от стандартной библиотеки Rust), который использует библиотеку (wasmi), которая уже поддерживает сборку no_std.Новичок в Rust, я просто соединяю воедино инструкции, но суть этого, кажется, , выполните шаги .

Для исполняемого файла:

#![no_std]
#![no_main]

use core::panic::PanicInfo;

/// This function is called on panic.
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
    loop {}
}

#[no_mangle]
pub extern "C" fn _start(_argc: isize, _argv: *const *const u8) -> ! {
    interpret(_argc, _argv);
    loop {}
}

То естьto:

  • include #![no_std]
  • определить нашу запись (не main, поскольку у нас нет среды выполнения, которая будет ее вызывать)
  • и определитьобработчик паники, поскольку библиотека Rust std не включена для его определения.

Файл My Cargo для компиляции выглядит следующим образом:

[package]
 name = "driver"
 version = "0.1.0"
 edition = "2018"

[dependencies.wasmi]
 path = "../../github_dev/wasmi" 
 features = ["core"]
 default-features = false
 test=false
 bench=false

 [profile.release]
 panic = "abort"
 lto = true
 incremental=false
 debug=true
 opt-level = "z"
 test=false
 bench=false

и выдает очень маленький файл.двоичный файл, который исключает любые символы стандартной библиотеки (для проверки используется nm) и работает как положено.

Проблема возникает, когда я на самом деле пытаюсь вызвать функцию из библиотеки wasmi.Он построен с no_std по линии features=core.Выполнение nm для файлов в release/deps/libwasmi-*.rlib не показывает стандартных символов библиотеки.Однако, когда связывание происходит с этой командой:

rustc --release --verbose -- -C link-arg=-nostartfiles

, это приводит к:

   Compiling driver v0.1.0 (/home/my_home/wasmi_embed/driver)
     Running rustc --edition=2018 --crate-name driver src/main.rs --color always --crate-type bin --emit=dep-info,link -C opt-level=3 -C panic=abort -C lto -C link-arg=-nostartfiles -C metadata=957eda2e590447ba -C extra-filename=-957eda2e590447ba --out-dir /home/my_home/wasmi_embed/driver/target/release/deps -L dependency=/home/my_home/wasmi_embed/driver/target/release/deps --extern libc=/home/my_home/wasmi_embed/driver/target/release/deps/liblibc-f7fb773c7b059a14.rlib --extern wasmi=/home/my_home/wasmi_embed/driver/target/release/deps/libwasmi-534aef1926b4eb6c.rlib

и возникает ошибка:

error[E0152]: duplicate lang item found: panic_impl.
  --> src/main.rs:31:1
   |
31 | / pub extern fn panic(_info: &PanicInfo) -> ! {
32 | |     loop {}
33 | | }
   | |_^
   |
   = note: first defined in crate `std`.

Кажется, что Rust пытаетсяссылка в стандартной библиотеке поддержки по крайней мере для обработки паники, но я не знаю, почему.

Я хотел бы помочь понять, почему и как предотвратить это.

Если я удалюpanic_impl атрибут, то мой исполняемый файл компилируется, но он содержит много стандартных библиотечных символов, которые я пытаюсь предотвратить.

Примеры символов, которые я вижу:

my_home@my_puter:~/wasmi_embed/driver/target/release$ nm --demangle -A -a -B -s --line-number test_2018 2>/dev/null | grep std
driver:00000000000264c0 t rust_begin_unwind  /rustc/8e2063d02062ee9f088274690a97826333847e17//src/libstd/panicking.rs:311
driver:00000000000264a0 t rust_oom   /rustc/8e2063d02062ee9f088274690a97826333847e17//src/libstd/alloc.rs:203
driver:000000000001f490 t rust_panic /rustc/8e2063d02062ee9f088274690a97826333847e17//src/libstd/panicking.rs:524
driver:0000000000025aa0 t _$LT$std..panicking..continue_panic_fmt..PanicPayload$LT$$u27$a$GT$$u20$as$u20$core..panic..BoxMeUp$GT$::get::he4f810e299a2e0b4    /rustc/8e2063d02062ee9f088274690a97826333847e17//src/libstd/panicking.rs:372
driver:00000000000259a0 t _$LT$std..panicking..continue_panic_fmt..PanicPayload$LT$$u27$a$GT$$u20$as$u20$core..panic..BoxMeUp$GT$::box_me_up::hd8430725259668a8     /rustc/8e2063d02062ee9f088274690a97826333847e17//src/libstd/panicking.rs:367
driver:0000000000021520 t _$LT$std..sys_common..process..DefaultEnvKey$u20$as$u20$core..borrow..Borrow$LT$std..ffi..os_str..OsStr$GT$$GT$::borrow::hbacd0cd7d7fbf1c1/rustc/8e2063d02062ee9f088274690a97826333847e17//src/libstd/sys_common/process.rs:27
driver:0000000000021570 t _$LT$std..error..$LT$impl$u20$core..convert..From$LT$alloc..string..String$GT$$u20$for$u20$alloc..boxed..Box$LT$$LP$dyn$u20$std..error..Err
... plus more

Вышеуказанные символы не найдены ни в одном из файлов rlib в каталоге dep, включая libwasmi, а также в драйвере.исполняется, когда не вызывается код libwasmi.

Я прочитал аналогичную проблему (отсюда мои test=false и bench=false в Cargo.toml), но это не помогло.Я пытался собрать только с rustc с различными командами (исключая Cargo), но ошибка та же.Я пытался скомпилировать wasmi как статическую библиотеку (ar) и связать ее, но, будучи новичком в Rust, я тратил много времени, пытаясь связать его, а этого просто не было.

1 Ответ

0 голосов
/ 14 февраля 2019

Я решил эту проблему после того, как обратился за помощью на форумы по ржавчине. введите описание ссылки здесь .В частности, я не смог определить, что было причиной того, что ржавчина std lib была связана с моим исполняемым файлом ... была ли это проблема с корзиной, проблема с грузом, проблема с rustc или проблема с компоновщиком.Я не знал, где возникла проблема, но, основываясь на схожих найденных ошибках, я подумал, что каким-то образом компилируется ящик для неожиданного ввода std lib.Оказывается, ошибка введите описание ссылки здесь не было связано, хотя сообщение об ошибке было то же самое.У меня не было проблемы с неожиданным распространением различных типов зависимостей (dev-зависимость и сборка зависимости).Я попробовал все эти методы, чтобы точно определить, что приносит std lib:

  1. Я попытался использовать дерево грузов для отображения зависимостей, чтобы перечислить все зависимости crate:

    wasmi v0.4.3 (/ home / jlb6740 / github_dev / wasmi)
    ├── byteorder v1.3.1 (/ home / jlb6740 / github_dev / byteorder)
    ├── hashbrown v0.1.8 (/ home / jlb6740 / github_dev / hashbrown)
    │ ├── byteorder v1.3.1 (/ home / jlb6740 / github_dev / byteorder) ()
    │ └── scopeguard v0.3.3 (/ home / jlb6740 / github_dev / scopeguard)
    ├── libm v0.1.2
    ├── memory_units v0.3.0
    └── parity-wasm v0.31.0 (/ home / jlb6740 / github_dev / parity-wasm)
    └── byteorder v1.3.1 (/ home / jlb6740 / github_dev / byteorder) (
    )

  2. Я пытался использовать cargo rustc --verbose… но в настоящее время verbose ничего не указываетиспользовал функции по умолчанию, которые могут включать в себя использование STD

  3. Я пытался использовать метаданные груза ... это генерироватьd длинный список зависимостей, которые было трудно проанализировать, но я видел случаи, когда scopeguard и byteorder имели функции по умолчанию, требующие поддержки std.Я загрузил все эти ящики и только жестко закодированные атрибуты, чтобы ящики собирались только с поддержкой no_std.

  4. Я попытался посмотреть на deps / output и сделал nm для всех rlibs.чтобы увидеть, использовала ли какая-либо из библиотек символы, найденную в std.Я не мог найти, что это было так.Я думал, что rlibs похожи на статические библиотеки и что все, что они использовали, будет включено в rlib, но, очевидно, нет.

  5. Я посмотрел на cargo rustc - -C --print-link-argsчтобы проверить флаги компоновщика, но я не смог найти ничего очевидного, говорящего мне, что он вводит стандартную библиотеку.

Ничто из этого не помогло мне точно определить, что вводит стандартную библиотеку.В конечном итоге на форумах по ржавчине было предложено использовать проверку груза для цели, которая вообще не допускает стандартную загрузку.Те, у кого * указаны здесь: введите описание ссылки здесь имеют только поддержку ядра.Я попробовал это, запустив с --target=thumbv7m-none-eabi и увидел:

ошибка [E0463]: не могу найти ящик для alloc
-> /home/jlb6740/github_dev/hashbrown/src/lib.rs:44: 1
|
44 |стандартный внешний ящик как alloc;
|^^^^^^^^^^^^^^^^^^^^^^^^^^ не могу найти ящик

Оказывается, это был hashbrown, который зависел отзависимость моего исполняемого файла.Он построил no_std по умолчанию, но имел extern std, связанный под другим именем и защищенный функцией, называемой «nightly».Охранник был отключен в моих попытках не создавать ничего, кроме no_std.Ничто из того, что я пробовал, не предупредило меня о ящике, который отвечал до этого.Кажется, должен быть лучший способ получить более полный список зависимостей от ящиков, чем то, что предоставляло грузовое дерево, но изменение груза wasmi, чтобы убедиться, что ночная функция была установлена, решило мою проблему.

...