Ошибка "множественное определение` memcmp "при компоновке Rust staticlib со встроенной программой на C - PullRequest
0 голосов
/ 20 мая 2018

У меня есть функция Rust, которую я хотел бы вызвать из C проекта , который работает на микроконтроллере STM32F412, но я получаю серию ошибок компоновщика "множественное определение".

Вот мой lib.rs:

#![crate_type = "staticlib"]
#![feature(lang_items)]
#![no_std]
#![no_builtins]

#[no_mangle]
pub extern "C" fn hello_world(a: i32, b: i32) -> i32 {
    a + b
}

#[lang = "eh_personality"] extern fn eh_personality() {}
#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }

Сборка с cargo build --release --target=thumbv7em-none-eabihf дает librust.a, который я добавил как объект в Makefile на C.

Полный список ошибок компоновщика можно найти здесь .nm показывает все конфликтующие функции как глобальные текстовые символы (T), полный вывод здесь .

Проект C не имеет нормальной стандартной библиотеки C, вместо этого он использует собственный libcспецифичная для устройства реализация, которая покрывает небольшую часть стандарта.Могу ли я указать библиотеке Rust использовать эти функции?

При чтении списка функций Rust есть #![feature(compiler_builtins_lib)], но это прямо противоположно тому, что я хочу, поскольку, если вы получаете "неопределенную ссылку на"ошибки компоновщика.

1 Ответ

0 голосов
/ 21 мая 2018

У вас есть набор дублированных символов, поступающих из вашей настраиваемой "стандартной библиотеки" liba и сгенерированных встроенных символов, вставленных в librust.a:

memset, memcpy, memmove, ecc, ecc

Возникла ваша проблемапотому что порядок объектных файлов имеет значение при связывании.

Если вы поставите librust.a слишком рано в упорядоченной последовательности файлов для связывания, то файлы до librust.a будут разрешать символы из librust.a и файлы, следующие послеlibrust.a разрешит те же символы из liba, и это приведет к дублированию ошибок символов.

Чтобы избежать этой проблемы, поместите библиотеку Rust в конце объектных файлов для ссылки.

В файле makefile epsilon измените команды ссылки следующим образом:

RUST_LIB_DIR = <path_to_librust.a>

.SECONDARY: $(objs)
%.$(EXE):
    @echo "LD      $@"
    $(Q) $(LD) $^ $(LDFLAGS) -L$(RUST_LIB_DIR) -l:librust.a -o $@ 

Этот рецептссылки успешно на моей стороне.Моя базовая epsilon/apps/main.cpp аппаратура:

#include "global_preferences.h"
#include "apps_container_storage.h"

extern "C" int hello_world(int a, int b);

void ion_main(int argc, char * argv[]) {

  hello_world(1,2);
  ...
...