Active Topics

 


Reply
Thread Tools
Posts: 88 | Thanked: 411 times | Joined on Mar 2010 @ southern Italy
#1
I happen to love Rust programming language (already running my code on ARM targets like Jolla phone and Beagleboard).

I just found a way to cross-compile Rust programs to run on a N900.

Scenario:
- write/debug some Rust program on my Ubuntu PC
- cross-compile it for ARMv7 target (thanks, Rustup!)
- copy executable file on the N900 and execute it there.

On the N900:
- have a directory with updated libc/ldso/libgcc_s...
- use it:
Code:
LD_LIBRARY_PATH=/root/rust ./myrustprogram
Why this ugly solution:
- latest Rust releases require at least glibc 2.18 on the target N900
- (and glibc versions newer than 2.18 require kernel 2.6.32 or newer)
- I didn't want to try risky upgrades.

N900 preparation:
- grab a glibc 2.18 binary (I found one from OpenSUSE 13.1/ARM)
- grab the related libgcc_s binary (I found one from OpenSUSE 13.2/ARM)
- unpack them on your desktop PC, for example:
Code:
mkdir tmp
cd tmp
rpm2cpio glibc-2.18-4.44.1.armv7hl.rpm | cpio -idmv 
rpm2cpio libgcc_s1-4.8.3+r212056-2.2.1.armv7hl.rpm | cpio -idmv
- create a "rust" directory on the N900 in some place where executable bit is supported, for example:
Code:
ssh root@n900 mkdir /root/rust
- copy libraries (libc-2.18.so and so on) extracted from the glibc 2.18 and libgcc_s packages (will waste some 3.5 Mb of your precious disk space), for example:
Code:
rsync -ave ssh lib/* /root/rust/
- create a symbolic link to the new loader:
Code:
ssh root@n900 ln -s /root/rust/ld-linux-armhf.so.3 /lib
Typical workflow on desktop PC:
Code:
cargo new mytest --bin
cd mytest
vi src/main.rs
cargo build --quiet --release --target=armv7-unknown-linux-gnueabihf
cd target/armv7-unknown-linux-gnueabihf/release
arm-linux-gnueabihf-strip mytest
rsync -ave ssh mytest root@n900:/root/
And then, on the N900:
Code:
LD_LIBRARY_PATH=/root/rust /root/mytest
Note: you don't need to be root, as long as libraries are readable/executable.

Why did it work?
- Rust-compiled executables only require a few essential libraries (generally libc, libm, libpthread, libdl)
- Rust-compiled executables are happy with glibc 2.18 (this is why the same executable for N900 works on the Beagleboard and Jolla phones)
- I was lucky: N900 stock software uses legacy ld-linux.so.3 loader name instead of ld-linux-armhf.so.3

Note:
- a trick like this will work on any platform as long as it uses the legacy loader name and the kernel is not too old for the glibc "updated" version;
- some "updated" features may require extra fiddling (nsswitch, rpc, bindresvport; check the etc directory of the glibc package if you need them).

Mission: accomplished.
Attached Images
 
 

The Following 15 Users Say Thank You to alfmar For This Useful Post:
Posts: 88 | Thanked: 411 times | Joined on Mar 2010 @ southern Italy
#2
Forgot to add:

- you need to install Rustup (which allows to install both Rust compiler and the extra platforms for cross-compiling)

- adding ARM platform target:
Code:
rustup target install armv7-unknown-linux-gnueabihf
- then add these two lines to ~/.cargo/config
Code:
[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"
- then install ARM-linux; for example, in Ubuntu:
Code:
sudo apt-get install gcc-arm-linux-gnueabihf
More on my scripts directory.

To deploy executables to Jolla SailfishOS no extra steps are required. For N900 you need the glibc 2.18 thing (and LD_LIBRARY_PATH) as described above.
 

The Following 3 Users Say Thank You to alfmar For This Useful Post:
Posts: 207 | Thanked: 552 times | Joined on Jul 2011
#3
I'd be interested to know if Rust and the Nuklear UI library (Rust bindings here) could be used to write apps that run on Sailfish.
 
Posts: 88 | Thanked: 411 times | Joined on Mar 2010 @ southern Italy
#4
As a rule of thumb, if you don't need to link at compile time any existing libraries, you're a go.

I was able to add X11 basic support to N900 Rust programs.

There is an x11-dl Rust "crate" that dinamically loads X11 libraries. I successfully used it to create a Rust program using X11 graphics system, test it on my Ubuntu 16.04 desktop, then cross-compile targetting N900.

X11 library is messy, but getting it to link is quite a big leap.

Step 1: create a new Rust project for a binary executable, for example:
Code:
cargo new x11n900 --bin
Step 2: enter the newly-created directory and edit the Cargo.toml file (conceptually a "makefile" for Rust), filling a dependencies section with default libc and x11-dl crates:
Code:
[dependencies]
libc = "*"
x11-dl = "*"
Step 3: edit some Hello World example (like this one, that only shows a white empty window) for desktop PC, making cargo download, compile and link the x11-dl package source:
Code:
cargo run
Step 4: we now need a small hack in the x11-dl source because the lib X11 6.2.0 on the N900 is quite old and does not support four functions present in lib X11 6.3.x and x11-dl.

Edit the file ~/.cargo/registry/src/github*/x11-dl-*/src/xlib.rs to:
- change the x11_link! macro line (not 767 functions but 763);
- then erase the four lines defining XESetCopyEventCookie, XESetWireToEventCookie, XFreeEventData, XGetEventData.

Actual patch should appear like this:
Code:
37c37
< x11_link! { Xlib, x11, ["libX11.so.6", "libX11.so"], 767,
---
> x11_link! { Xlib, x11, ["libX11.so.6", "libX11.so"], 763,
241d240
<   pub fn XESetCopyEventCookie (_3: *mut Display, _2: c_int, _1: Option<unsafe extern "C" fn (*mut Display, *mut XGenericEventCookie, *mut XGenericEventCookie) -> c_int>) -> Option<unsafe extern "C" fn (*mut Display, *mut XGenericEventCookie, *mut XGenericEventCookie) -> c_int>,
254d252
<   pub fn XESetWireToEventCookie (_3: *mut Display, _2: c_int, _1: Option<unsafe extern "C" fn (*mut Display, *mut XGenericEventCookie, *mut xEvent) -> c_int>) -> Option<unsafe extern "C" fn (*mut Display, *mut XGenericEventCookie, *mut xEvent) -> c_int>,
278d275
<   pub fn XFreeEventData (_2: *mut Display, _1: *mut XGenericEventCookie) -> (),
298d294
<   pub fn XGetEventData (_2: *mut Display, _1: *mut XGenericEventCookie) -> c_int,
Step 5: verify that it still compiles and runs: check with ldd the executable, it won't show X11 libraries link prerequisites:
Code:
cargo clean
cargo run
ldd target/debug/x11n900
Step 6: cross-compile to ARM target and copy to N900 to some temporary executable directory:
Code:
cargo build --target=armv7-unknown-linux-gnueabihf --release
rsync -ave ssh target/armv7-unknown-linux-gnueabihf/release/x11n900 root@n900:/root/rust/
Step 7: in the N900 terminal, logged in as "user" (X11 programs shouldn't run as root; I'm using /root/rust as a temporary work directory as in the example of the other posts), execute:
Code:
LD_LIBRARY_PATH=/root/rust/ /root/rust/x11n900
Why does it work?
- x11-dl loads the X11 libraries at run-time: no need to install N900 SDK Scratchbox stuff.
- N900 window manager adjusts the window size/position.

Any other ideas about writing graphics-enabled programs in Rust to run on the N900?
- you will need to fiddle with Scratchbox and graphics libraries sources and new versions
- N900 sports Gtk 2.0 and Qt 4.7, wxWidget 2.8 is available to install, but apparently no Rust bindings/gluecode exist for those old versions.

Disclaimer:
- I did it "because I can"; I can't recommend wasting time with that baroque libX11.
 

The Following 3 Users Say Thank You to alfmar For This Useful Post:
Posts: 88 | Thanked: 411 times | Joined on Mar 2010 @ southern Italy
#5
Arrrgh, slow, obscene, and I even had to manage redraw events...
Attached Images
 
__________________
 

The Following 2 Users Say Thank You to alfmar For This Useful Post:
Posts: 88 | Thanked: 411 times | Joined on Mar 2010 @ southern Italy
#6
Originally Posted by switch-hitter View Post
I'd be interested to know if Rust and the Nuklear UI library (Rust bindings here) could be used to write apps that run on Sailfish.
It seems that Nuklear doesn't support Wayland yet (SailfishOS does not use X11: yay!)
__________________
 
Reply

Tags
rustlang


 
Forum Jump


All times are GMT. The time now is 17:55.