[Rust] Cross compile linux and windows programs on mac (including Docker implementation)

1. Basic steps

  • Install the target's standard library with rustup target add
  • rustup target list View the list of supported targets
  • Install the target linker
  • Update cargo.toml to let rustc know which linker to use
  • cargo build --release --target TARGET_NAME

2. Prepare

The whole process may need to download the github package on the command line, and set the proxy in advance (modify according to your own situation):

export https_proxy=http://127.0.0.1:7890 http_proxy=http://127.0.0.1:7890 all_proxy=socks5://127.0.0.1:7890


3. Compile the linux program on the mac

3.1 Preparation

  • Choose the right target (standard library with target platform)

The common targets of linux are x86_64-unknown-linux-gnu and x86_64-unknown-linux-musl

  • The feature of musl is lightweight, no dependencies, and can run on any linux system. The disadvantage is that the compiled program is slower than glibc.
  • The characteristic of gnu is that it is faster, generates a dynamic link library, and installs glibc depending on the platform.
  • The following will introduce the installation steps of both, please choose one to install first (you may encounter some problems)
  • View the list of targets supported by Rust:
lei@WilldeMacBook-Pro learn_rust % rustup target list |sort -R
i686-unknown-freebsd
aarch64-apple-ios
x86_64-unknown-linux-musl (installed)
armv5te-unknown-linux-musleabi
i586-unknown-linux-gnu
arm-linux-androideabi
x86_64-linux-android
...几十种
  • View installed targets:
lei@WilldeMacBook-Pro learn_rust % rustup target list |grep installed
aarch64-apple-darwin (installed)   -- 这个默认安装的,因为当前平台就是m1pro,下面是手动安装的
x86_64-pc-windows-gnu (installed)
x86_64-pc-windows-msvc (installed)
x86_64-unknown-linux-gnu (installed)
x86_64-unknown-linux-musl (installed)

3.2 install target

Install musl: rustup target add x86_64-unknown-linux-musl
Install gnu:rustup target add x86_64-unknown-linux-gnu

3.3 Installing the linker

Install the musl linker: brew install filosottile/musl-cross/musl-cross
Install the gnu linker:brew install SergioBenitez/osxct/x86_64-unknown-linux-gnu

3.3 Change Cargo.toml

increase the following

[target.x86_64-unknown-linux-musl] # 也支持[build]节点 设置target=...
linker = "x86_64-linux-musl-gcc"
[target.x86_64-unknown-linux-gnu]
linker = "x86_64-unknown-linux-gnu-gcc"

3.3 Start compiling

Using musl: TARGET_CC=x86_64-linux-musl-gcc cargo build --release --target x86_64-unknown-linux-musl
using gnu:TARGET_CC=x86_64-unknown-linux-gnu cargo build --release --target x86_64-unknown-linux-gnu

3.4 Troubleshooting

Problem: If the final compilation times: ld: unknown option: --as-needed
Solution: Use another auxiliary tool cargo-zigbuild to compile (this tool is also written in rust to facilitate cross-compilation and solve some strange problems)

cargo install cargo-zigbuild
brew install zig
cargo zigbuild --release --target x86_64-unknown-linux-musl
或
cargo zigbuild --release --target x86_64-unknown-linux-gnu

4. Compile windows program on mac

Simplified logging:

rustup target add x86_64-pc-windows-gnu
brew install mingw-w64   # 链接器

Change Cargo.toml, add the following

[target.x86_64-pc-windows-gnu]
linker = "x86_64-w64-mingw32-gcc"
# [target.x86_64-pc-windows-msvc]  不需要填写linker

Note: To compile windows programs based on x86_64-pc-windows-msvc on mac/linux, please use another auxiliary tool: cargo-xwin

4.1 Troubleshooting

Problem: When compiling msvc at last: cargo xwin build --target x86_64-pc-windows-msvc, error:

error: failed to run custom build command for `rust-crypto v0.2.36`

Caused by:
  process didn't exit successfully: `/Users/lei/Desktop/Rust/learn_rust/target/debug/build/rust-crypto-a19246e40d1c0ac5/build-script-build` (exit status: 101)
  --- stdout
  TARGET = Some("x86_64-pc-windows-msvc")
  OPT_LEVEL = Some("0")
  TARGET = Some("x86_64-pc-windows-msvc")
  HOST = Some("aarch64-apple-darwin")
  TARGET = Some("x86_64-pc-windows-msvc")
  TARGET = Some("x86_64-pc-windows-msvc")
  HOST = Some("aarch64-apple-darwin")
  CC_x86_64-pc-windows-msvc = None
  CC_x86_64_pc_windows_msvc = Some("clang-cl --target=x86_64-pc-windows-msvc")
  TARGET = Some("x86_64-pc-windows-msvc")
  HOST = Some("aarch64-apple-darwin")
  CFLAGS_x86_64-pc-windows-msvc = None
  CFLAGS_x86_64_pc_windows_msvc = Some("-Wno-unused-command-line-argument -fuse-ld=lld-link /imsvc/Users/lei/Library/Caches/cargo-xwin/xwin/crt/include /imsvc/Users/lei/Library/Caches/cargo-xwin/xwin/sdk/include/ucrt /imsvc/Users/lei/Library/Caches/cargo-xwin/xwin/sdk/include/um /imsvc/Users/lei/Library/Caches/cargo-xwin/xwin/sdk/include/shared")
  DEBUG = Some("true")
  running: "clang-cl --target=x86_64-pc-windows-msvc" "-O0" "-ffunction-sections" "-fdata-sections" "-fPIC" "-Wno-unused-command-line-argument" "-fuse-ld=lld-link" "/imsvc/Users/lei/Library/Caches/cargo-xwin/xwin/crt/include" "/imsvc/Users/lei/Library/Caches/cargo-xwin/xwin/sdk/include/ucrt" "/imsvc/Users/lei/Library/Caches/cargo-xwin/xwin/sdk/include/um" "/imsvc/Users/lei/Library/Caches/cargo-xwin/xwin/sdk/include/shared" "-g" "--target=x86_64-pc-windows-msvc" "-Wall" "-Wextra" "/Fo/Users/lei/Desktop/Rust/learn_rust/target/x86_64-pc-windows-msvc/debug/build/rust-crypto-21fe17a56301ca99/out/src/util_helpers.o" "/c" "src/util_helpers.c"

  --- stderr
  thread 'main' panicked at '

  Internal error occurred: Failed to find tool. Is `clang-cl --target=x86_64-pc-windows-msvc` installed?

It is because the rust-cypto library that the code depends on internally relies on the old version of the gcc library, and the new version of clang-cl does not support it, so the easiest way is to replace the rust-crypto library that has not been updated for more than 6 years by 2022 and use the new The RustCrypto library.

The blogger tried to brew to install the old version of gcc, but it was prompted that the upstream version of gcc had been abandoned and could not be installed; so he did not continue to try (as of the post, the blogger has studied Rust cross-compilation for more than 6 hours)

Solution: Modify Cargo.toml

[dependencies] 
# rust-crypto = "0.2.36"
sha2 = "0.10.6"
sha3 = "0.10.6"

5. Easier way - use Docker

Regardless of the language, if you want to achieve developer-friendly cross-compilation, you have to hand over this work to Docker, and Rust is no exception.
In this way, there is no need to toss the developer's host, nor does it take a lot of time to deal with various dependency issues.
The following refers to rust-musl-cross

5.1 Pull the required image

Such as x86_64-musl, others please find from the above link

$ docker pull messense/rust-musl-cross:x86_64-musl

5.2 Modify config

cd PROJECT/src/   # 进入项目的src目录
vi ~/.cargo/config    添加target部分(与Cargo.toml的target一致)如下

[target.x86_64-unknown-linux-musl] 
linker = "x86_64-linux-musl-gcc"

Note that this step is very important, because when the blogger was operating, he found that the target configuration based on Cargo.tom originally built on the mac in the container did not take effect. The result was cc: error: unrecognized command-line option '-m64'that an error was reported during the build. ld: unknown option: --as-neededThe rust compiler cannot find the correct linker through configuration, so please remember.
In addition, if you want to know how to fill in the information of other targets, in the next step, remove the .cargo/config mapping, and then directly execute rust_builder. After entering the container, copy its content to cat ~/.cargo/configyour local ~/.cargo/config That's it.

5.3 Build docker command

alias rust_builder='docker run -it --rm -v "$(pwd)":/home/rust/src \
                -v "/Users/lei/.cargo/config:/root/.cargo/config" \
                -v "/Users/lei/.cargo/registry:/root/.cargo/registry" \
                -v "/Users/lei/.cargo/git:/root/.cargo/git" \
            messense/rust-musl-cross:x86_64-musl'
# 注意替换上面-v选项后面的路径为你本地路径,它们主要提供构建的缓存功能,以实现下次构建的加速,避免重复工作

# nightly构建
rust_builder rustup default nightly && rustup target add x86_64-unknown-linux-musl && cargo build --target x86_64-unknown-linux-musl --release
# stable构建
rust_builder cargo build --target x86_64-unknown-linux-musl --release

5.4 Troubleshooting

When trying to build target= armv7-unknown-linux-musleabihf, the following error is reported during build:

error: linker `armv7-unknown-linux-musleabihf-gcc` not found
  |
  = note: No such file or directory (os error 2)

Then the blogger thought about it, if it would be different if he entered the container and then executed the command, so there are the following steps:

lei@WilldeMacBook-Pro learn_rust % alias rust_builder='docker run -it --rm -v "$(pwd)":/home/rust/src \                                                                                
                -v "/Users/lei/.cargo/config:/root/.cargo/config" \
                -v "/Users/lei/.cargo/registry:/root/.cargo/registry" \
                -v "/Users/lei/.cargo/git:/root/.cargo/git" \
            messense/rust-musl-cross:armv7-musleabihf'
lei@WilldeMacBook-Pro learn_rust % rust_builder
root@2fb71f01c5f4:/home/rust/src# rustup default nightly && rustup target add armv7-unknown-linux-musleabihf && cargo build --target armv7-unknown-linux-musleabihf
info: syncing channel updates for 'nightly-aarch64-unknown-linux-gnu'
info: latest update on 2022-10-23, rust version 1.66.0-nightly (6e95b6da8 2022-10-22)
info: downloading component 'cargo'
info: downloading component 'rust-std'
...

    Building [=========================> ] 94/95: learn_rust(bin)                                                                                                                                                                                                                                                     
warning: `learn_rust` (bin "learn_rust") generated 151 warnings (1 duplicate)
    Finished dev [unoptimized + debuginfo] target(s) in 2m 11s
root@2fb71f01c5f4:/home/rust/src# 

Wow! As you can see, this is actually all right, and the blogger doesn’t know what the problem is. If readers know a thing or two, please leave a message in the comment area for guidance~

Summarize

This article is a summary of bloggers who spent a lot of time stepping on pits (combined with sites such as cnblog/zhihu/stackoverflow/github/rust official website).




other information

Guess you like

Origin blog.csdn.net/sc_lilei/article/details/127460105