Есть пара вещей, о которых вы должны знать. Что наиболее важно, версия LLVM, которую rustc использует по умолчанию, если вы получаете ее от rustup или диспетчера пакетов дистрибутива, не является/ не/ фактическим выпуском LLVM и может фактически быть несовместима по битовому коду с конкретным выпуском llvm. Мы решили эту проблему в моем проекте, собрав rust из исходников с флагом --llvm-root
для настройки. Затем вы можете использовать rustup toolchain link
, чтобы связать ваш собранный rustc с пользовательской цепочкой инструментов rustup.
Во-вторых, вы можете заставить rustc создавать файлы .rlib, содержащие битовый код llvm вместо машинного кода, если вы используете rustc версии не ниже 1.34 и передадите флаг -C linker-plugin-lto в rustc. Я также написал следующий сценарий, который может распаковать файл rlib, содержащий объектный код, и упаковать его обратно в виде файла rlib, содержащего битовый код llvm, если описанный выше подход не работает для вас.
#!/bin/bash
dir="$(mktemp -d)"
trap "rm -rf $dir" INT TERM EXIT
archive=$(realpath -m $1)
cd "$dir"
ar x "$archive"
rm ./*.rcgu.o
for file in *.bc.z; do
len=`od -An -t u4 -j 15 -N4 $file`
blen=`od -An -t u8 -j $((len+19)) -N8 $file`
tail -c+$((len+28)) $file | head -c $blen > $file.bc.gz
printf "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x00" |cat - $file.bc.gz |gzip -dc > ${file%.bc.z}.o
done
rm *.bc.z
rm *.gz
rm "$archive"
llvm-ar rs "${archive}" ./*
После того, как у вас есть файлы rlib, вы можете использовать для них любой инструментарий llvm так же, как и с файлом .a, содержащим битовый код llvm.
Что касается выполнения последней ссылки, следует помнить о нескольких вещах. Во-первых, rustc автоматически генерирует символы __rust_alloc
, __rust_alloc_zeroed
, __rust_dealloc
и __rust_realloc
и указывает их либо на __rg_alloc
(и аналогичные символы __rg_
соответственно), что является реализацией GlobalAlloc, использующей jemalloc по умолчанию, либо на __rdl_alloc
(и аналогичные символы __rdl_
соответственно). который является системным распределителем на базе libc malloc. Вам придется реализовать эти символы самостоятельно, если вы не используете rustc для создания окончательной ссылки.
Во-вторых, libstd и libcore зависят от некоторых других библиотек, с которыми вам, вероятно, также придется связываться. В зависимости от того, какой сегмент стандартной библиотеки вы используете, вы можете обнаружить, что требуются разные наборы библиотек, поэтому я не могу вам помочь без конкретного сообщения об ошибке, но я могу сказать вам, что список библиотек, которые мое приложение в итоге потребовалось, по порядку: std, core, alloc, unwind, compiler_builtins, panic_abort, backtrace_sys, rustc_demangle
. Если вы используете panic=unwind, вам, очевидно, придется использовать его вместо этого. Если вы обнаружите, что у вас все еще есть отсутствующие символы, я бы предложил использовать nm для поиска библиотеки, содержащей отсутствующий символ, и выяснить, где он находится в порядке компоновщика методом проб и ошибок.
Надеюсь, это поможет, так как я потратил немало усилий на разработку решения именно этой проблемы (хотя и не для целей кросс-компиляции).
31.05.2019