Building a cross-platform application (using Rust) - cross-platform

I started to learn Rust programming language and I use Linux. I'd like to build a cross-platform application using this language.
The question might not be related to Rust language in particular, but nonetheless, how do I do that? I'm interested in building a "Hello World" cross-platform application as well as for more complicated ones. I just need to get the idea.
So what do I do?
UPDATE:
What I want to do is the ability to run a program on 3 different platforms without changing the sources. Do I have to build a new binary file for each platform from the sources? Just like I could do in C

To run on multiple platforms you need to build an executable for each as #huon-dbauapp commented.
This is fairly straightforward with Rust. You use "--target=" with rustc to tell it what you want to build. The same flag works with Cargo.
For example, this builds for an ARM target:
cargo build --target=arm-unknown-linux-gnueabihf
See the Rust Flexible Target Specification for more about targets.
However, Rust doesn't ship with the std Crate compiled for ARM (as of June 2015). If this is the case for your target, you'll first need to compile the std Crates for the target yourself, which involves compiling the Rust compiler from source, and specifying the target for that build!
For information, most of this is copied from: https://github.com/japaric/ruststrap/blob/master/1-how-to-cross-compile.md
The following instructions are for gcc, so if you don't have this you'll need to install it. You'll also need the corresponding cross compiler tools, so for gcc:
sudo apt-get install gcc-arm-linux-gnueabihf
Compile Rust std Crate For ARM
The following example assumes you've already installed the current Rust Nightly, so we'll just get the sources and compile for ARM. If you are using a different version of the compiler, you'll need to get that to ensure your ARM libraries match the version of the compiler you're using to build your projects.
mkdir ~/toolchains
cd ~/toolchains
git clone https://github.com/rust-lang/rust.git
cd rust
git update
Build rustc for ARM
cd ~/toolchains/rust
./configure --target=arm-unknown-linux-gnueabihf,x86_64-unknown-linux-gnu
make -j4
sudo make install
Note "-j4" needs at least 8GB RAM, so if you hit a problem above try "make" instead.
Install ARM rustc libraries In native rustc build
sudo ln -s $HOME/src/rust/arm-unknown-linux-gnueabihf /usr/lib/rustlib/arm-unknown-linux-gnueabihf
Create hello.rs containing:
pub fn main() {
println!("Hello, world!");
}
Compile hello.rs, and tell rustc the name of the cross-compiler (which must be in your PATH):
rustc -C linker=arm-linux-gnueabihf-gcc-4.9 --target=arm-unknown-linux-gnueabihf hello.rs
Check that the produced binary is really an ARM binary:
$ file hello
hello: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), (..)
SUCCESS!!!:
Check: the binary should work on an ARM device
$ scp hello me#arm:~
$ ssh me#arm ./hello
Hello, world!
I've used this to build and link a Rust project with a separate C library as well. Instructions similar to the above on how to do this, dynamically or statically are in a separate post, but I've used my link quota up already!

The best way to figure this out is to download the source code for Servo and explore it on your own. Servo is absolutely a cross-platform codebase, so it will have to address all of these questions, whether they be answered in build/configuration files, or the Rust source itself.

It looks like the rust compiler might not be ready to build standalone binaries for windows yet (see the windows section here), so this probably can't be done yet.
For posix systems it should mostly Just Work unless you're trying to do GUI stuff.

Yes, you won't need to change the source, unless you are using specific libraries that are not cross-platform.
But as #dbaupp said native executables are different on each platform, *nix uses ELF, Windows PE, and OSX Mach-O. So you will need to compile it for each platform.
I don't know the state of cross-compiling in rust, but if they already implemented it, then you should be able to build all the binaries in the same platform, if not, you will have to build each binary on it's platform.

Related

How can I compile perl6 file to exe

I am playing with perl6 version which built on MoarVM on windows. I created some perl6 file and want to compile it to exe. I tried the following:
perl6 --target=MAST r.pl>r
Now I want to compile the r to executable
I found this link which talk about how to that using Parrot but I am using MoarVM target: http://perlgeek.de/blog-en/perl-6/my-first-executable.writeback
my question how can i compile MoarvVM targeted file to windows executable ?
Unfortunately, the answer is to target JVM and one of the many nice tools for turning a JAR into an executable. MoarVM doesn't have that tooling at this point (and given the lack of current overlap between perl6 hackers and Windows users, probably won't for some time).
One of the things that attracted me to the language, was that it was supposed to be compilable, I thought "sure, it would build exe files for me", unfortunately, it does not (last I checked).
compile:
perl6 --target=mbc --output=test.moarvm -e 'say 42'
run:
perl6 -e 'CompUnit::Loader.load-precompilation-file("test.moarvm".IO)'
However, you can compile the program t the intermediate moarvm machine, do KEEP IN MIND this is not porable, so you have to recompile on each target.
I think this code was legated to me by somebody that really knew perl6 on the irc channel, I don't understand how it works, though.
I advise if you need a compiled language, to wait for real support from the compiler guys or simply to use something like rust or golang (that is what I ended up using, I'm happy).
I know rust doesn't have all the "bells and whistles" that Perl6 has, but it gets the job done...

Build and link µIP library with no OS

I'm relitavely new to embedded development and I have a question, or more of a feedback, on building and linking the µIP library on an embedded device. For what it's worth, the following is using a FOX G20 V board with an ATMEL AT91SAM9G20 processor with no OS.
I have done some research, and the way I see myself building and linking the library on the board is one of the following two options.
Option 1: The first option would be to compile the whole library (the .c files) in order to have a built static library in the form of a .a file. Then, I can link the created static library with my application code, before loading it on the device. Of course, the device driver will have to be programmed in order to allow the library to work on the platform (help was found here). This first option is using a Linux machine. For this first option as well, in order to load the static library linked with my application code, do I do so with an "scp"?
Option 2: The second option would be to compile and link the library to my application code directly without going through an intermediate static library. However, since my platorm does not contain an OS, I would need to install an appropraite GCC compiler in order to compile and link (if anyone has any leads for such an installation, that would be very helpful as well). However I'm quite unfamilier with the second option, but I've been told that it is easier to implement so if anyone as an idea on how to implement it, it would be very helpful.
I would appreciate some feedback along with the answers as to whether these options seem correct to you, and to be sure that I have not mentioned something that is false.
There is no real difference between these options. In any case, the host toolchain is responsible for creating a binary file that contains a fully linked executable with no external dependencies, so you need a cross compiler either way, and it is indeed easiest to just compile uIP along with the rest of the application.
The toolchain will typically have a cross compiler (if you use gcc, it should be named arm-eabi-gcc or arm-none-eabi-gcc), cross linker (arm-eabi-ld), cross archiver (arm-eabi-ar) etc. You would use these instead of the native tools. For Debian, you can find a cross compiler for ARM targets without an OS in testing/unstable.
Whether you build a static library
arm-eabi-gcc -c uip.c
arm-eabi-ar cru uip.a uip.o
arm-eabi-ranlib uip.a
arm-eabi-gcc -o executable application.c uip.a
or directly link
arm-eabi-gcc -c application.c
arm-eabi-gcc -c uip.c
arm-eabi-gcc -o executable application.o uip.o
or directly compile and link
arm-eabi-gcc -o executable application.c uip.c
makes no real difference.
If you use an integrated development environment, it is usually easiest to just add uip.c as a source file.

Anyone use GMP on Xeon Phi?

I compiled GMP with icc and -mmic option, but can't install on MIC. How should I install?
I wrote a demo program, compiled with icc. It says can't find gmp.h.
How should I install GMP library on MIC and where to place gmp.h?
Build GMP with Intel Compiler:
cd /home/
wget https://gmplib.org/download/gmp/gmp-6.0.0.tar.bz2
tar -xf gmp-6.0.0.tar.bz2
rm -f gmp-6.0.0.tar.bz2
cd gmp-6.0.0
mkdir mic
cd mic
../configure CC=icc CFLAGS="-mmic" --host=x86_64 --disable-assembly --prefix /home/gmp-6.0.0/mic/
make
make install
Use the Intel Compiler with environment variables for mic development:
GMP_INCDIR=/home/gmp-6.0.0/mic/include
GMP_LIBDIR=/home/gmp-6.0.0/mic/lib
Though I don't have any expertize on Xeon Phi or even ICC if you are running on Unix-like environment, then you might to try to step through normal configure/make procedure on GMP sources pointing on ICC compiler instead of default GCC in order to build static and/or shared library along with generated gmp.h header, that you can then link with your application. You might want to see GMP documentation on that. Here are some advices, that I stepped to trying to compile it for NVIDIA CUDA:
Supply ./configure with CC and CFLAGS variables to point to desired compiler and its whatever options that you want
Be sure that there is no ABI incompability between your host and Xeon Phi device, especially between 32 and 64 bit architecture.
Consider adding --disable-assembly option to generate "pure-C" build (I am not familiar with Xeon Phi assembly and if/how it is compatibile with x86)
Don't forget to run make check (possibly with -j parameter) after you compiled GMP in order to check if tests are passing, it's very important step if you want use it for some professional purpose.
The library is installed in OS by make install command, for default under /usr/local directory (you might add --prefix option if you want it somewhere else), specifically:
/usr/local/include for gmp.h header file
/usr/local/lib for static and/or shared libgmp binaries
You might also try to compile your application with mini-gmp package, which is contained within GMP sources (it's located under mini-gmp directory). It's a subset of mpz_* and mpn_* routines, not as sophisticated and fast as normal GMP (and it doesn't have as much serious tests coverage), but it could make the job done with small footprint (it's contained in one header and C-source file). For such option be sure to obtain most recent version of GMP (or even get it from their repository).

Static library GNUSTEP and correct linking

I was checking out the portability of Objective-C via gnustep and ran into some problems...
I mean everything works on my 2 machines but the major problem is if I run my application on a platform where gnustep is not pre-installed... So I want to build it with static libraries. But I ran into several problems:
1.) I cant find the static libaries under /usr/local/lib so the question came up do they even exist within gnustep?
2.) In case there are static libraries available how to integrate it correctly into my gcc command?
sudo gcc -o main main.m GameRef.m SDLApplication.m SDLEvent.m SDLImage.m SDLMap.m SDLSprite.m Settings.m Utility.m -I -static `gnustep-config --variable=GNUSTEP_SYSTEM_HEADERS` -L `gnustep-config --variable=GNUSTEP_SYSTEM_LIBRARIES` -lgnustep-base -lSDL -fconstant-string-class=NSConstantString -std=c99 2>logFile
I'm currently using Ubuntu 12.04LTS and installed the SDL and Gnustep on one machine so the application runs fine... But not on the second because the shared libraries are missing so I need to add them as static but how?
The libraries in /usr/local/lib and other system 'lib' directories will be dynamic. They can't be used as static (AFAIK), and finding them wouldn't really help.
I'm no expert with GNUstep, but it sounds like you are missing the Objective-C runtime. You will need to download the source code of the GNUstep libraries and frameworks, and then compile them into static libraries yourself.
Really, wrapping all of those frameworks into your application will just add unnecessary work for both you and your end users. Dynamic libraries exist for a purpose. There's no reason to have multiple copies of the same code on the filesystem. Just require GNUstep as a dependency. Although its a slight pain for the users, they only need to do it once, and with most distros, installation is only a command or two away.

How to cross compile CMake for ARM with CMake

In short I'm trying to cross compile CMake with CMake, and I don't think I'm linking libraries correctly. What I want to do may not be possible, but I'd at least like to know why it isn't possible if that's the case.
System: The host is a Linux box with a Cavium ARM9 CPU. It's currently running version 2.6.24.4 of the Linux kernel and Debian 5.0 (Lenny). My workstation is a Core i5 running Ubuntu 12.04 LTS (Precise Pangolin).
My overall goal is to get ROS running on the Linux box. I have to compile from source rather than use apt since Debian 6.0 (Squeeze) binaries require thumb support that the Cavium does not give, and not many of the needed packages are available for Debian 5.0 (Lenny). I'd made progress installing the various libraries needed, but when I got to step 1.3.1 and tried to run CMake, I got the error
CMake 2.8 or higher is required. You are running version 2.6.0
Next I tried to download and build CMake 2.8.8 on the Linux box itself, but it was too much for the system. When that failed, I downloaded the toolchain suggested on the manufacturer's website and used the cross-compiling guide at [www.cmake.org/Wiki/CMake_Cross_Compiling] to build the CMake executables. Here is my toolchain file:
# This one is important
SET(CMAKE_SYSTEM_NAME Linux)
# Specify the cross compiler
SET(CMAKE_C_COMPILER /pathto/crosstool-linux-gcc-4.5.2-gclibc-2.9-oabi/arm-unknown-linux-gnu/bin/arm-unknown-linux-gnu-gcc)
SET(CMAKE_CXX_COMPILER /pathto/crosstool-linux-gcc-4.5.2-gclibc-2.9-oabi/arm-unknown-linux-gnu/bin/arm-unknown-linux-gnu-g++)
# Where is the target environment
SET(CMAKE_FIND_ROOT_PATH /pathto/crosstool-linux-gcc-4.5.2-gclibc-2.9-oabi/arm-unknown-linux-gnu /pathto/crosstool-linux-gcc-4.5.2-gclibc-2.9-oabi/arm-unknown-linux-gnu/arm-unknown-linux-gnu)
# Search for programs in the build host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# For libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
However, use of the binary on the Linux box gives the error
cmake: /usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.14' not found (required by cmake)
Sure enough, the library is not there:
prompt# strings /usr/lib/libstdc++.so.6 | grep GLIBC
GLIBCXX_3.4
GLIBCXX_3.4.1
GLIBCXX_3.4.2
GLIBCXX_3.4.3
GLIBCXX_3.4.4
GLIBCXX_3.4.5
GLIBCXX_3.4.6
GLIBCXX_3.4.7
GLIBCXX_3.4.8
GLIBCXX_3.4.9
GLIBCXX_3.4.10
GLIBC_2.3
GLIBC_2.0
GLIBC_2.3.2
GLIBC_2.1
GLIBC_2.1.3
GLIBC_2.2
GLIBCXX_FORCE_NEW
GLIBCXX_DEBUG_MESSAGE_LENGTH
I've never cross-compiled before, but I can see one of two scenarios happening: either the binary got created with a link to a higher version of glibcxx on the host machine or the manufacturer's toolchain is more modern than their image. I don't know how to check which is happening or if something else is happening that I don't know about.
My last effort involved trying to statically cross-compile CMake to hopefully get rid of the linking error with
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain-technologic.cmake -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXE_LINKER_FLAGS_RELEASE="-static" ..
I got build errors, and that binary didn't work either. I got:
FATAL: kernel too old
Segmentation fault
I'd try installing glibcxx 3.4.14 on the Linux box, but it doesn't look like it's available for this processor.
I've tried searching for CMake dependencies or system requirements and can't find anything. I've also searched on how to build CMake, but most searches turn up how to build other things with CMake rather than building CMake itself.
I do cross-compile a lot for ARM9 devices using CMake, and indeed this looks like you're not linking to the same libs you have on your target device. You shouldn't need to build CMake yourself to get this done, since it does have good support for cross-compiling since version 2.6. Just make sure you set the CMAKE_FIND_ROOT_PATH variable to a path where you have an exact copy of the root filesystem you have on your target device (with libraries and binaries pre-compiled for the target processor). That should solve your problems.
As a sidenote, I like to use crosstool-ng for building my cross-compilers. It is a really nice tool which helps you to build them from scratch, so I try to match the compiler version and glibc to the ones originally used to build the root filesystem (I usually start with a ready made root filesystem from ARMedslack, since I use Slackware for my development box and ARMedslack for my ARM targets).