Compile a Rust program to an exe using an M1 mac? - macos

I have written a program in Rust on my M1 Mac, and compiled it to a Unix executable just fine. Now I want to compile it to a Windows executable as well. I first tried
$ cargo target add x86_64-pc-windows-gnu
$ cargo build --release --target=x86_64-pc-windows-gnu
I got the error message:
error: linker x86_64-w64-mingw32-gcc not found
so I tried
$ brew install mingw-w64
according to this, and got the error:
Error: mingw-w64: no bottle available!
I looked on formulae.brew.sh and it seems that mingw-w64 isn't supported for M1, only Intel.
How can I compile an exe from rust using my M1 Mac?

Solution 1:
You can install/add the targets using these commands :
rustup target add x86_64-pc-windows-gnu
rustup toolchain install stable-x86_64-pc-windows-gnu
then you can target windows from your mac:
cargo build --release --target=x86_64-pc-windows-gnu
Solution 2:
Simply use docker!
FROM mcr.microsoft.com/windows/servercore:ltsc2019
// install rust
COPY project c:/project
RUN cd c:/project && cargo build --release
Solution 3:
there is also Cross. you can use this for cross-compilation:
https://github.com/rust-embedded/cross

I'm going to jump in with a couple newer solutions that worked really well for me:
cargo-zigbuild
Targets (*-pc-windows-gnu afaik):
i686-pc-windows-gnu
x86_64-pc-windows-gnu
cargo-zigbuild also supports cross-compiling to other platforms out of the box as well, with no containerization needed!
Quick example:
brew install zig
cargo install cargo-zigbuild
cargo zigbuild --target x86_64-pc-windows-gnu -r
cargo-xwin
Targets (*-msvc afaik):
aarch64-pc-windows-msvc
i586-pc-windows-msvc
i686-pc-windows-msvc
x86_64-pc-windows-msvc
Quick example:
cargo install cargo-xwin
cargo xwin build --target x86_64-pc-windows-msvc -r
Which one do I pick?
See: Difference between the gnu and msvc toolchains?
TL;DR: Use msvc/cargo-xwin for "more native" windows binaries (that are smaller in size) & use gnu/cargo-zigbuild to help porting over a linux-specific application.

Related

GitHub Actions Runner Image - boost for macOS arm64

How do I deploy boost for arm64 to a GitHub Actions Runner Image under macOS?
I am using Github Actions to build my project, which depends on boost.
As far as I can tell, when I set the YAML label to macos-11, the runner image itself is intel.
For my x86_64 build, I simply say
brew install boost
And the job can then go on to compile and link my own code successfully.
If I understand correctly, it is not possible to use brew to install boost arm64 binaries to a macOS intel machine.
Maybe I could build boost from source using something like
./bootstrap.sh
./b2 install
What flags would I pass to tell it to cross compile the arm64 binaries?
Edit: I found the solution and posted the answer below, stack overflow tells me that I do not have enough karma to mark my own answer as accepted.
At the bottom of this page...
B2 4.7.1 MacOS Armv8 package bundles x86_64 binary
...it says:
./b2 architecture=arm address-model=64 -s NO_LZMA=1 -s NO_ZSTD=1 abi=aapcs
That worked for me. The entire step that I have on github actions is:
- name: Boost
run: |
curl -O -L https://boostorg.jfrog.io/artifactory/main/release/1.80.0/source/boost_1_80_0.tar.gz
tar xfz boost_1_80_0.tar.gz
cd boost_1_80_0
./bootstrap.sh
./b2 architecture=arm address-model=64 -s NO_LZMA=1 -s NO_ZSTD=1 abi=aapcs install
lipo /usr/local/lib/libboost_*.dylib -info

How can I cross compile Rust code into Intel assembly on an ARM M1 Apple Silicon Mac?

I've been comparing the assembly code generated by C and Rust for x86 and ARM.
I have an M1 Mac and I found how to cross-compile C with Clang, but so far I can't find how to cross-compile Rust.
How can I generate an x86_64 binary from Rust on an M1 Mac?
Cross-compilation is built in, just use rustup to install the target support:
$ rustup target install x86_64-apple-darwin
and build your crate like this:
$ cargo build --target x86_64-apple-darwin
Thanks to Rosetta you can even run it like this:
$ cargo run --target x86_64-apple-darwin

Compiling gRPC on MacOS for Darwin ARM64 - using bazel or cmake instead of make

OS: MacOS 11
Platform: Apple M1 architecture (Darwin ARM64)
According to
https://chromium.googlesource.com/external/github.com/grpc/grpc/+/HEAD/BUILDING.md
using make is outdated.
I downloaded and installed bazel Darwin x64 (MacOS Intel) binary latest version, bazel build :all completed without errors.
bazel test --config=dbg //test/... however prints out a lot of errors after a few minutes of compiling.
There's also the option to run cmake, which also completes.
So, my question is, am I correct if cmake or bazel (with build :all, of course) does not install the binaries, but rather make and (sudo) make install do?
If the use of make is "outdated", is bazel / cmake used to install the compiled binaries?

Cross-compiling Rust from Windows to ARM Linux

I'm using Windows 10. I would like to cross-compile a Rust program to run on armv7-unknown-linux-gnueabihf. (armv7-unknown-linux-muscl would also be acceptable but it doesn't seem to be available.)
Here are my steps:
Install rustup
rustup toolchain install stable-x86_64-pc-windows-gnu
rustup toolchain default stable-x86_64-pc-windows-gnu
rustup target add armv7-unknown-linux-gnueabihf
Edit my ./cargo/config file to contain:
[build]
target = "armv7-unknown-linux-gnueabihf"
cargo build
This compiles everything fine, but when it comes to linking it gives this error:
error: could not exec the linker `cc`: The system cannot find the file specified. (os error 2)
As far as I have been able to determine, this is because Rust doesn't have its own linker and uses GCC instead. Apparently I need to provide this myself and add this to the ./cargo/config file:
[target.armv7-unknown-linux-gnueabihf]
linker = "c:/path/to/my/gcc/cross/compiler"
Is that right? If so where on Earth can I download such a cross-compiler for Windows and why doesn't rustup install it? Having to compile a cross-compiling version of GCC yourself is the biggest pain of cross-compiling C/C++ programs. Does Rustup really not make this any easier?
Thanks to #Notlikethat's comment:
a) Yes you need to provide your own GCC cross-compiler.
b) You can get one here (select a mingw32 build).
Just unzip linaro's GCC then point cargo to it:
[target.armv7-unknown-linux-gnueabihf]
linker = "C:/Users/me/gcc-linaro-5.3.1-2016.05-i686-mingw32_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc.exe"
It seems to work even though it is arm- and not armv7-. I guess linking doesn't depend on the ISA. Actually I haven't run it yet, but it builds without errors!
Edit:
You can now use armv7-unknown-linux-musleabihf instead and get an actually portable binary (i.e. it doesn't depend on the GNU C library which often causes compatibility issues).
For MacOS better use: musleabihf, for Windows you can use gnueabihf as bellow:
Mac
$ brew install arm-linux-gnueabihf-binutils
$ rustup target add armv7-unknown-linux-musleabihf
In .cargo/config
[build]
target = "armv7-unknown-linux-musleabihf"
[target.armv7-unknown-linux-c]
linker = "arm-linux-gnueabihf-ld"
With simple src/main.rs
fn main() {
println!("Hello, Raspberry!");
}
Then things are fine:
Hasans-Air:rpi hasan$ cargo build
Compiling rpi v0.1.0 (/Users/hasan/PycharmProjects/rpi)
Finished dev [unoptimized + debuginfo] target(s) in 0.41s
Hasans-Air:rpi hasan$ scp target/armv7-unknown-linux-musleabihf/debug/rpi pi#192.168.1.43:
pi#192.168.1.43's password:
rpi 100% 2702KB 2.6MB/s 00:01
Hasans-Air:rpi hasan$ ssh pi#192.168.1.43 'chmod +x ~/rpi && ~/rpi'
pi#192.168.1.43's password:
Hello, Raspberry!
Win 10
Get the linker from here, and run:
rustup target add armv7-unknown-linux-gnueabihf
Creating file .cargo/config with content:
[build]
target = "armv7-unknown-linux-gnueabihf"
[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"
And with simple src/main.rs:
fn main() {
println!("Hello, Raspberry! from Win 10");
}
I was able to get things done

compile Boost as static Universal binary lib

I want to have a static Universal binary lib of Boost. (Preferable the latest stable version, that is 1.43.0, or newer.)
I found many Google hits with similar problems and possible solutions. However, most of them seems outdated. Also none of them really worked.
Right now, I am trying
sudo ./bjam --toolset=darwin --link=static --threading=multi \
--architecture=combined --address-model=32_64 \
--macosx-version=10.4 --macosx-version-min=10.4 \
install
That compiles and install fine. However, the produced binaries seems broken.
az#ip245 47 (openlierox) %file /usr/local/lib/libboost_signals.a
/usr/local/lib/libboost_signals.a: current ar archive random library
az#ip245 49 (openlierox) %lipo -info /usr/local/lib/libboost_signals.a
input file /usr/local/lib/libboost_signals.a is not a fat file
Non-fat file: /usr/local/lib/libboost_signals.a is architecture: x86_64
Edit: It seems that the command was wrong and I must remove the "--" for most options. So the command I am trying now (-a just means to rebuild all):
sudo ./bjam -a toolset=darwin link=static threading=multi \
architecture=combined address-model=32_64 \
macosx-version=10.4 macosx-version-min=10.4 \
install
However, this gives many strange errors (what I already had earlier), all like this:
darwin.compile.c++.pch bin.v2/libs/math/build/darwin-4.2.1/release/address-model-32_64/architecture-combined/link-static/macosx-version-min-10.4/macosx-version-10.4/threading-multi/../src/tr1/pch.hpp.gch
In file included from ./boost/math/special_functions/acosh.hpp:18,
from ./boost/math/special_functions.hpp:15,
from libs/math/build/../src/tr1/pch.hpp:9:
./boost/config/no_tr1/cmath.hpp:21:19: error: cmath: No such file or directory
This could be another problem I have when building Universal binaries: g++ on MacOSX doesn't work with -arch ppc64
I found the problem. It seems that the MacOSX 10.4 SDK is missing a bunch of symlinks for GCC 4.2.
Use this as a test case:
g++ on MacOSX doesn't work with -arch ppc64
It will report multiple errors with GCC 4.2 (missing C++ includes, missing C includes, missing libs). In all cases, you can just fix that by setting a symlink. Search in your SDK for the file and just set the symlink in the same way it is in the MacOSX 10.5 SDK.
After that, it all just worked.
We use Boost compiled for 10.4 here at work. We don't use GCC 4.2 on it though, rather we use GCC 4.0 as Apple's GCC 4.2 is not supported for the MacOS 10.4 SDK. To accomplish this you need a bjam user config file, eg. user-config-darwin.jam. Here's the contents of ours. Modify to your heart's content:
# Boost.Build Configuration
# Compiler configuration
using darwin : 8.11 : /usr/bin/g++-4.0 :
<architecture>"combined"
<address-model>"32" # this can be changed to 32_64 for 32/64 universal builds
<macosx-version>"10.4"
<macosx-version-min>"10.4"
# <root>"/Developer"
<compileflags>""
<linkflags>"" ;
Then, you need to tell bjam to use the user config jam file when compiling:
bjam --user-config=user-config-darwin.jam ... (your other options go here) ...
Now you don't have to mess with symlinks in the system SDK directories.
To build 4-way universal boost static binaries on OSX 10.6 I do the following:
Download boost from the boost website.
Extract the archive and cd into the boost_1_xx_0 folder (where xx is the version of boost you are using).
Run:
./bootstrap.sh and then
./bjam macosx-version=10.6 macosx-version-min=10.4 architecture=combined threading=multi link=static address-model=32_64
This will compile everything except for Boost.MPI (which requires the --with-mpi option). The build products get put in ./stage

Resources