nto-qnx
层级:3
QNX® Neutrino (nto) 实时操作系统。该支持由 Elektrobit Automotive GmbH 和 Blackberry QNX 共同实施。
目标维护者
- Florian Bartels,
[email protected]
, https://github.com/flba-eb - Tristan Roach,
[email protected]
, https://github.com/gh-tr - Jonathan Pallant
[email protected]
, https://github.com/jonathanpallant - Jorge Aparicio
[email protected]
, https://github.com/japaric
要求
目前,支持以下 QNX Neutrino 版本和编译目标
QNX Neutrino 版本 | 目标架构 | 完全支持 | no_std 支持 |
---|---|---|---|
7.1 | AArch64 | ✓ | ✓ |
7.1 | x86_64 | ✓ | ✓ |
7.0 | x86 | ✓ |
可以添加 QNX Neutrino 支持的其他架构。
在上表中,“完全支持”表示支持使用完整标准库构建 Rust 应用程序。“no_std
支持”表示仅提供 core
和 alloc
。
要为 QNX Neutrino 构建或使用 Rust 工具链,必须安装并初始化 QNX 软件开发平台 (SDP)。初始化通常通过获取 qnxsdp-env.sh
来完成(这将作为 SDP 的一部分安装,另请参见 SDP 提供的安装说明)。之后,qcc
(QNX C/C++ 编译器)应该可用(在 $PATH
变量中)。例如,qcc
将用于链接可执行文件。
链接 no_std
应用程序时,它们必须链接到 libc.so
(参见示例)。这是必需的,因为应用程序始终链接到 crt
库,而 crt
依赖于 libc.so
。使用标准库时,这会自动完成。
小型示例应用程序
下面显示了一个小型 no_std
示例。使用标准库的应用程序也可以正常工作。
#![no_std]
#![no_main]
#![feature(lang_items)]
// We must always link against libc, even if no external functions are used
// "extern C" - Block can be empty but must be present
#[link(name = "c")]
extern "C" {
pub fn printf(format: *const core::ffi::c_char, ...) -> core::ffi::c_int;
}
#[no_mangle]
pub extern "C" fn main(_argc: isize, _argv: *const *const u8) -> isize {
const HELLO: &'static str = "Hello World, the answer is %d\n\0";
unsafe {
printf(HELLO.as_ptr() as *const _, 42);
}
0
}
use core::panic::PanicInfo;
#[panic_handler]
fn panic(_panic: &PanicInfo<'_>) -> ! {
loop {}
}
#[lang = "eh_personality"]
#[no_mangle]
pub extern "C" fn rust_eh_personality() {}
Rust 对 QNX Neutrino 的支持已在 QNX Neutrino 7.0 和 7.1 中测试。
没有其他已知要求。
条件编译
对于条件编译,定义了以下 QNX Neutrino 特定属性
target_os
="nto"
target_env
="nto71"
(对于 QNX Neutrino 7.1)target_env
="nto70"
(对于 QNX Neutrino 7.0)
构建目标
- 创建
config.toml
示例内容
profile = "compiler"
change-id = 115898
- 为
x86_64-unknown-linux-gnu
主机(对于aarch64
和x86_64
目标)编译 Rust 工具链
编译 Rust 工具链需要与编译 C 二进制文件相同的环境变量。请参阅 QNX 开发人员手册。
要为 QNX Neutrino(aarch64 和 x86_64)和 Linux(x86_64)编译
export build_env='
CC_aarch64-unknown-nto-qnx710=qcc
CFLAGS_aarch64-unknown-nto-qnx710=-Vgcc_ntoaarch64le_cxx
CXX_aarch64-unknown-nto-qnx710=qcc
AR_aarch64_unknown_nto_qnx710=ntoaarch64-ar
CC_x86_64-pc-nto-qnx710=qcc
CFLAGS_x86_64-pc-nto-qnx710=-Vgcc_ntox86_64_cxx
CXX_x86_64-pc-nto-qnx710=qcc
AR_x86_64_pc_nto_qnx710=ntox86_64-ar'
env $build_env \
./x.py build \
--target aarch64-unknown-nto-qnx710,x86_64-pc-nto-qnx710,x86_64-unknown-linux-gnu \
rustc library/core library/alloc library/std
运行 Rust 测试套件
Rust 编译器和标准库的测试套件可以像其他 Rust 目标一样执行。测试环境应与编译器编译期间使用的环境匹配(参考上面的 build_env
和 qcc
/PATH
),并添加 TEST_DEVICE_ADDR 环境变量。TEST_DEVICE_ADDR 变量控制远程运行器,应指向目标,尽管以下示例中显示的是 localhost。请注意,一些测试正在失败,这就是为什么它们目前被目标维护者排除的原因,这可以在以下示例中看到。
要在 x86_64 QNX Neutrino 目标上运行所有测试
export TEST_DEVICE_ADDR="localhost:12345" # must address the test target, can be a SSH tunnel
export build_env='
CC_aarch64-unknown-nto-qnx710=qcc
CFLAGS_aarch64-unknown-nto-qnx710=-Vgcc_ntoaarch64le_cxx
CXX_aarch64-unknown-nto-qnx710=qcc
AR_aarch64_unknown_nto_qnx710=ntoaarch64-ar
CC_x86_64-pc-nto-qnx710=qcc
CFLAGS_x86_64-pc-nto-qnx710=-Vgcc_ntox86_64_cxx
CXX_x86_64-pc-nto-qnx710=qcc
AR_x86_64_pc_nto_qnx710=ntox86_64-ar'
# Disable tests that only work on the host or don't make sense for this target.
# See also:
# - src/ci/docker/host-x86_64/i686-gnu/Dockerfile
# - https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/Running.20tests.20on.20remote.20target
# - .github/workflows/ci.yml
export exclude_tests='
--exclude src/bootstrap
--exclude src/tools/error_index_generator
--exclude src/tools/linkchecker
--exclude tests/ui-fulldeps
--exclude rustc
--exclude rustdoc
--exclude tests/run-make-fulldeps'
env $build_env \
./x.py test \
$exclude_tests \
--stage 1 \
--target x86_64-pc-nto-qnx710
构建 Rust 程序
Rust 尚未为此目标提供预编译的工件。要为此目标编译,您必须启用目标构建 Rust(参见上面的“构建目标”),或者通过使用 build-std
或类似方法构建自己的 core
副本。
测试
编译后的可执行文件可以直接在 QNX Neutrino 上运行。
Rust std 库测试套件
目标需要足够的资源来执行所有测试。以下命令假设使用 QEMU 映像。
-
确保
remote-test-server
使用的临时目录有足够的可用空间和 inode。已知 5GB 的可用空间和 40000 个 inode 足够(测试将创建超过 32k 个文件)。要在空目录中创建 QEMU 映像,请在目录中运行以下命令mkqnximage --type=qemu --ssh-ident=$HOME/.ssh/id_ed25519.pub --data-size=5000 --data-inodes=40000
/data
应该有足够的可用资源。在运行remote-test-server
时,相应地设置TMPDIR
环境变量,例如TMPDIR=/data/tmp/rust remote-test-server --bind 0.0.0.0:12345
-
确保 TCP 堆栈可以处理足够的并行连接(默认值为 200,应为 300 或更高)。在创建映像(参见上文)后,编辑文件
output/build/startup.sh
- 搜索
io-pkt-v6-hc
- 添加参数
-ptcpip threads_max=300
,例如io-pkt-v6-hc -U 33:33 -d e1000 -ptcpip threads_max=300
- 使用与创建映像相同的参数再次运行
mkqnximage
来更新映像。
- 搜索
-
运行和停止虚拟机
要启动虚拟机,请在 VM 的目录中运行
mkqnximage --run=-h
要停止虚拟机,请在 VM 的目录中运行
mkqnximage --stop
-
确保本地网络
确保“localhost”解析为 127.0.0.1。如果您无法 ping localhost,则某些测试可能会失败。确保将其附加到 /etc/hosts(如果第一个
ping
命令失败)。命令必须在虚拟机中执行!$ ping localhost ping: Cannot resolve "localhost" (Host name lookup failure) $ echo "127.0.0.1 localhost" >> /etc/hosts $ ping localhost PING localhost (127.0.0.1): 56 data bytes 64 bytes from 127.0.0.1: icmp_seq=0 ttl=255 time=1 ms
交叉编译工具链和 C 代码
编译 C 代码需要设置与编译 Rust 工具链相同的环境变量(参见上文),以确保 qcc
使用正确的参数。为了确保兼容性,不要指定任何其他参数,例如更改调用约定或内存布局。