How Crossplatform is rust really?


#1

Hi all,

I read online that it is possible to create a target in the Cargo.toml and then produce an executable that works on the targeted platform. I wonder if anyone here can give me some input about how well that works in real life. Can I create any application e.g. on windows and compile for any other platform (linux, android, bsd etc.) or are there some pitfalls that prevent me from doing so? Also, are there crossplatform gui libraries that work on all platforms?

I haven’t used rust yet and I don’t really want to learn rust just to find out how well that works. Any input about real life experiences in this regard would be greatly appreciated.


Best way to install Rust on OS X: rustup or brew?
#2

Rust is not a “write once, run anywhere” system in the ways that Java and the Web Platform are.

When we say that Rust is “cross platform”, we are not making a very strong claim; we are only saying that Rust, being a much younger system than C and with only one known implementation, has not developed ecosystem fragmentation yet. Rust won’t help you write code to run on multiple platforms (its system interfaces are at roughly the same level as the current-generation C++ standard libraries); however, it won’t get in your way with “having to support several largely incompatible compilers” either.

(If you’re looking for a “crossplatform gui library” that provides a native interface on “[Windows], Linux, Android, BSD”, I think you’re going to be disappointed regardless of language. The mobile user interface field seems quite fragmented.)


#3

Thanks for the info.

I did not mean to run the binary on any platform. The way I understood the info was more that you can choose for which platform you want to compile. So that I could work on windows and compile to e.g OS X without having to own a mac, yet still expect the compiled binary to work on one.

Are there any plans for a cross platform gui library? Maybe something similar to QML (it does not need to have a native look)?


#4

Well, in a limited way: libstd does work on all of our platforms, that helps. It’s platform-specific behavior or poorly-tested libraries you have to worry about.


#5

It works with some limitations:

  • You still need a linker that can link binaries of the target platform (cross linker)
  • If you depend on C libraries, I suspect that you also need those, compiled for the target platform.

I’m currently using this to compile from OS X -> ARMv7 Linux and all I had to do is find a suitable cross linker and add it to my cargo configuration.
But finding a suitable cross linker can be tricky, depending on the platforms.


#6

Not sure if this counts as a real-life experience but I am making a game in my free time on my mac using gfx-rs. My build seems to build just fine in windows using the msvc flavor of the rust windows build. Pretty surprised this actually worked since I think I am already at left-pad levels of dependencies.

I haven’t tried https://github.com/rust-lang-nursery/rustup.rs yet but I imagine that ought to be able to produce android and ios builds hopefully?


#7

Thanks for all the info!

I think I got a better picture now. If I understand correctly, rust is not specifically designed to be cross platform. However, it does not yet have a large platform fragmentation. As a result porting your code to a different platform should be straight forward and rather painless. Further more it is possible to setup tool chains (cross linkers etc) to build for other platforms but that is under development and may change in the future. That means so far rust would be a good choice when developing for various platforms, as the necessary adjustment should be minimal.

Are there concrete plans to build some sort of a one push deployment? So that you can develop and build on a single platform but deploy to any other? (I mean official plans to build this in, not private projects.)

Also, are there generally recommended GUI libraries yet?


#8

Have you seen rustup? This gives you a really simple and great way to download different versions of the compiler, allowing you to cross-compile to almost any platform from an platform, works fantastically!


#9

Rust - the language and stdlib - are designed to be cross-platform. It is also designed, though, to give direct access to platform features on need, so anyone along the line can break that (TBQH: that is also possible in Java-Land easily). Also, the toolchain is geared towards making cross-compiling easy and possible.

Rust compiles to specific platforms though, so any compile attempt requires the platforms cross-compile environments, which may be easy (Linux, BSD, etc) or hard/close to impossible to get (OS X, Windows). We are trying to make it easier as much as possible, the first current target is getting an Android development setup easily. rustup is the first step towards that.


#10

Have a look at https://github.com/japaric/rust-everywhere, works quite nicely for me.


#11

Thanks everyone for the additional info. I also didn’t know about rustup and rust-everywhere. This looks awesome. I guess the best is to just get started and write some small samples.


#12

I’ve been using Rust recently to cross compile geckodriver from 64-bit Linux to different architectures and toolchains such as Windows, ARM, FreeBSD, 32-bit Linux, and musl. My conclusion so far is that Rust does not provide the best experience for cross compilation compared to some other languages: Go in particular shines in this area, where % env GOOS=window go build hello.go will just do the right thing.

However, if you combine Rust with rustup, it will give you an easy way to install new compile targets. Each of the installed targets can in turn be passed to cargo build --target TARGET making it rather easy to do cross compilation for alternative architectures that are well supported on your system.

For example, to produce a 32-bit executable on a 64-bit Linux system:

# dpkg --add-architecture i386
# apt update
% rustup target add i686-unknown-linux-gnu
% cargo build --target i686-unknown-linux-gnu

It gets more complicated when you need to use alternative linkers, for example when cross compiling to Windows:

# apt install gcc-mingw-w64 gcc-mingw-w64-x86-64 binutils-mingw-w64-x86-64
% rustup target add x86_64-pc-windows-gnu
% cat >>.cargo/config <<EOF
[target.x86_64-pc-windows-gnu]
linker = "x86_64-w64-mingw32-gcc"
EOF
% cargo build --target x86_64-pc-windows-gnu

In my opinion it’s a mistake to not allow -C linker=LINKER to be passed through to rustc from the cargo UI. In continuous integration environments, that are typically one-off throwaway virtual machines, it would save a lot of effort if you did not have to write to the cargo config file.

There are also some targets that I’m being told it’s not possible to cross compile to, such as macOS. I would love for someone more familiar with linkers and macOS to share more insight on this. For those of us writing userland programs for wide distribution across different architectures and platforms, being able to cross-compile statically linked executables to each of the major operating systems would be extremely helpful.


#13

It’s not exactly cross compiling, but @japaric has done an amazing job at setting up Travis CI and AppVeyor to produce binaries for all 3 platforms for mdBook. I think it’s based on rust-everywhere mentioned above. It works amazingly well and could be an alternative to cross compiling in the mean time :slight_smile:


#14

Disclaimer: I’m not a gopher. This may be wrong.

My understanding is that cross compilation in Go is simpler because:

  • The linker (which now is written in Go?) is embedded in the Go compiler. So no need for a external linker.
  • Go programs don’t use libc in some cases so no need for a cross compiled libc.

My guess is that once you need to cross compile a Go program between different OSes (Linux -> macOS) that needs to link to a C library (cocoa?), cross compilation becomes as complicated as Rust’s.

You can with:

$ cargo rustc --target $TARGET -- -C linker=$LINKER

or:

$ RUSTFLAGS="-C linker=$LINKER" cargo build --target $TARGET

You can cross compile from Linux to macOS but it’s more complicated than other cross compilation setups. Here’s a script that cross compiles servo from Linux to macOS.


#15

Thanks, the tips will come in handy!

I have been reading up on rustup and had the following thought. D-Lang uses DUB as a package manager which allows to have different configurations in one dub.json file. E.g.

{
	"name": "foo",
	"configurations": [
	{
		"name": "debug",
		"targetPath": "bin/debug",
		"buildOptions": ["debugMode", "debugInfo"],
	},
	{
		"name": "release",
		"targetPath": "bin/release",
		"buildOptions": ["releaseMode", "optimize", "inline"],
	}
	]
}

so that you can use:

$ dub build --config=release

Shouldn’t it be possible to do something similar with cargo? I mean you could install all the tools (cross linker etc.) for the desired target platform, maintain a single Cargo.toml and just choose the appropriate configuration when building your project. At least in my mind it sounds easier to update Cargo rather than maintaining something like rustup :). No offence to the guys building that project though, I am just curious! Is there a reason why that’s not possible or why it hasn’t been done this way?


#16

Cargo already includes this: http://doc.crates.io/manifest.html#the-profile-sections

The main issue is, with Cargo.toml, we try to do better than just “a list of flags you pass to the compiler.” So we haven’t set up something in this area yet, but doesn’t mean that we might not in the future.


#17

I missed that part. Still new to rust :blush: Thanks for the hint.