#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
для вашего загрузчика с голым металлом.