Compile to mutliple targets at once

As we have multiple target platform in Rust, I've a library that is required to be compiled for both Android and Raspberry I fixed the linker of each target in the /.cargo/config file as below:

[target.arm-linux-androideabi]
linker = "/home/rust/android-18-toolchain/bin/arm-linux-androideabi-clang"

[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc-8"

And I was able to build the library as below 2 commands:

, and and we can build executable/library for each target by one of the below 2 methods (not sure if there are other ways):

~$cargo build --target=arm-linux-androideabi
~$cargo build --target=armv7-unknown-linux-gnueabihf

I aware I can add the [build] in the /.cargo/config if I want to build for single platform, as shown here by writting:

[build]
target = "arm-linux-androideabi"

to avoid using $cargo build --target=arm-linux-androideabi

I tried to add the other target, so it became like:

[build]
target = "armv7-unknown-linux-gnueabihf"
target = "wasm32-unknown-unknown"

[target.arm-linux-androideabi]
linker = "/home/rust/android-18-toolchain/bin/arm-linux-androideabi-clang"

[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc-8"

But got the below error upon trying ~$cargo build:

hyousef@DESKTOP-KPD1Q5Q:/mnt/d/raspberry$ cargo build
error: could not load Cargo configuration

Caused by:
could not parse TOML configuration in /home/hyousef/.cargo/config

Caused by:
could not parse input as TOML

Caused by:
duplicate key: target for key `build

1 Like

This is not possible. You'll have to make a script or makefile that runs both commands.

1 Like

I created file build.sh with the below:

echo "Running script commands";
cargo build;
cargo build --target=wasm32-unknown-unknown;
cargo build --target=armv7-unknown-linux-gnueabihf;
# cargo build --target=arm-linux-androideabi;

And run it as: ~$ sh build.sh it performed the required perfectly, but as I'm new for writting *.sh file, I think there is something wrong, and this is why i got multiple : not found: build.sh: as below, any idea?

hyousef@DESKTOP-KPD1Q5Q:/mnt/d/raspberry$ sh build.sh
Running script commands
: not found: build.sh:
Compiling raspberry v0.1.0 (/mnt/d/raspberry)
Finished dev [unoptimized + debuginfo] target(s) in 1.53s
: not found: build.sh:
Compiling raspberry v0.1.0 (/mnt/d/raspberry)
Finished dev [unoptimized + debuginfo] target(s) in 1.13s
: not found: build.sh:
Compiling raspberry v0.1.0 (/mnt/d/raspberry)
Finished dev [unoptimized + debuginfo] target(s) in 2.27s
: not found: build.sh:
hyousef@DESKTOP-KPD1Q5Q:/mnt/d/raspberry$

It might be a problem that only occurs on WSL:
https://askubuntu.com/a/969966
You can use a text editor that supports saving the file with Unix line endings. For example, in Visual Studio Code there is a button in the bottom bar that shows "LF" or "CRLF". Open the script, set it to "LF", save the file, and it should run fine (if my initial assumption was correct).

1 Like

I suspect you have Windows line-endings (\r\n), whereas sh is only consuming Unix line-endings (\n). So it's seeing this like cargo build;\r\n and interpreting this as a semicolon separating two commands, cargo build and \r, and the latter gives you the "not found" error.

Normally you don't need semicolons in sh scripts at the end of the line, but I think it's sort of saving you from this line-ending problem in this case.

1 Like

You are correct, I'm using Windows 10, and running the .sh through a Ubuntu shell installed using WSL, so it looks I've to lie with it, as removing the ; isngiving the below error:

hyousef@DESKTOP-KPD1Q5Q:/mnt/d/raspberry$ sh build.sh
Running script commands
rror: no such subcommand: build

    Did you mean `build`?

error: failed to run rustc to learn about target-specific information

Caused by:
' --crate-type bin --crate-type rlib --crate-type dylib --crate-type cdylib --crate-type staticlib --crate-type proc-macro(exit code: 1) --- stderr error: Error loading target specification: Could not find specification for target "wasm32-unknown-unknown\r" | = help: Use--print target-list` for a list of built-in targets

error: failed to run rustc to learn about target-specific information

Caused by:
' --crate-type bin --crate-type rlib --crate-type dylib --crate-type cdylib --crate-type staticlib --crate-type proc-macro(exit code: 1) --- stderr error: Error loading target specification: Could not find specification for target "armv7-unknown-linux-gnueabihf\r" | = help: Use--print target-list` for a list of built-in targets

Maybe try dos2unix on your build.sh script.

Thanks a lot, you are 100% correct.

I'm using ATOM and running Ubuntu shell in Win 10 through WSL. Your solution fixed my issue, even I do not need to use the ; any more.

Note: as per this tutorial I could make the build.sh as executable file by writting #!/bin/sh at the begining of the file, then executing it as ~$ ./build.sh

My updated script that run in both Windows and WSL is:

# !/bin/sh
#!/usr/bin/env/bash
echo "Running script commands at"
echo "os: " $OSTYPE
echo "host" $HOSTTYPE
if [ $OSTYPE == 'msys' ]
then
  echo "Building Windows library"
  cargo build --target=x86_64-pc-windows-msvc
elif [ $OSTYPE == 'linux-gnu' ]
then
  echo "Building Linux/WASM/Raspberry/Android libraries"
  cargo build --target=x86_64-unknown-linux-gnu
  cargo build --target=wasm32-unknown-unknown
  cargo build --target=armv7-unknown-linux-gnueabihf
  # cargo build --target=arm-linux-androideabi;
fi

echo "Building process completed, press any key to exit"
read
4 Likes