Двоичный файл Rust и библиотека не могут найти друг друга

#rust

Вопрос:

У меня есть статическая библиотека (ядро ОС в Rust), поэтому у меня есть файловое дерево:

  • Src/
  • src/lib.rs

Я добавил двоичный файл, чтобы я мог фактически запустить свое ядро (функции ядра реализованы в библиотеке). Это функция проекта, после включения она «позволяет» дополнительному src/main.rs файлу компилировать и запускать ядро, а также делает проект зависимым от bootloader ящика; если функция не включена, src/main.rs файл не компилируется, bootloader ящик не используется для проекта, и я src/lib.rs сам вызываю функции непосредственно из файла сборки, связывая статическую библиотеку, созданную rustc позже сам:

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

[lib]
crate-type = ["staticlib"]

# This is for the case of `src/bin/main.rs` which doesn't work as well.
#[[bin]]
#name = "main"
#required-features = ["bootloader"]

[dependencies.bootloader]
version = "0.10"
optional = true

[profile.dev]
panic = "abort"

[profile.release]
panic = "abort"

[features]
default = ["bootloader"]
 

Проблема в том, что main.rs я не могу видеть lib.rs , что бы я ни пытался:

lib.rs

 #![no_std]

#[no_mangle]
pub extern "C" fn main() -> i32 {
    0
}

#[no_mangle]
pub extern "C" fn kernel_early() {

}

pub fn myos_panic(info: amp;core::panic::PanicInfo<'_>) -> ! {
    loop {}
}
 

main.rs

 #![no_std]
#![no_main]

use myos::{kernel_early, main};

#[no_mangle]
pub extern "C" fn _start() -> ! {
    kernel_early();
    main();

    loop {}
}

use core::panic::PanicInfo;

#[panic_handler]
fn panic(info: amp;PanicInfo<'_>) -> ! {
    crate::myos_panic(info);
}
 

Название проекта в ящике таково myos . Вот что я до сих пор пытался использовать функции kernel_early и main из lib.rs модуля в main.rs :

 use myos::{kernel_early, main};
use crate::{kernel_early, main};
use super::{kernel_early, main};
 

Пробовал даже поиграть mod lib; use lib::* , конечно, от этого становилось только хуже.

Как мне заставить двоичный файл действительно работать с моей библиотекой? Я сделал тонны примеров грузов, и я знаю, как они работают, просто кажется, что это не работает с такой структурой проекта, где двоичный файл и библиотека находятся в одном ящике. Я также попытался переместить src/main.rs src/bin/main.rs «куда», но эффект был точно таким же.

Ошибки, которые у меня есть, следующие:

  --> src/main.rs:4:5
  |
4 | use myos::{kernel_early, main};
  |     ^^^^ use of undeclared crate or module `myos`

error[E0432]: unresolved imports `crate::kernel_early`, `crate::main`
 --> src/main.rs:4:13
  |
4 | use crate::{kernel_early, main};
  |             ^^^^^^^^^^^^  ^^^^ no `main` in the root
  |             |
  |             no `kernel_early` in the root

error[E0425]: cannot find function `myos_panic` in the crate root
  --> src/main.rs:18:12
   |
18 |     crate::myos_panic(info);
   |            ^^^^^^^^^^ not found in the crate root
 

P.S. Проблема не в искажении имени, так как я также пытался вызывать функции без его отключения.

Ответ №1:

Вы указали crate-type = ["staticlib"] для своей библиотеки, которая создает только библиотеку в собственном формате статической библиотеки целевого объекта. Вы не можете использовать такую библиотеку, как обычный ящик для ржавчины ( use myos:: ), потому что для этого требуется "rlib" (или, что эквивалентно, на данный момент "lib" ) тип ящика.

Я думаю, что это может сработать, если вы объявите функции в библиотеке так, как если бы они были функциями C, т. Е.

 extern {
   fn main() -> i32;
   fn kernel_early();
}
 

и ссылка на скомпилированный staticlib, как на библиотеку Си. (Я не знаю, как это на самом деле работает; я сам когда-либо использовал -sys ящики.)

Однако, если вы хотите сделать что-то ржавое, что невозможно сделать с помощью C ABI (например, универсальные функции), это вам не поможет. Если я правильно понимаю, ваш двоичный файл предназначен только для тестирования кода библиотеки. В этом случае вы можете изменить целевую конфигурацию на

 [lib]
crate-type = ["staticlib", "lib"]
 

а затем Cargo создаст оба формата: lib для вашего тестового двоичного файла и staticlib для вашего загрузчика с голым металлом.