rust
交叉编译
纯粹的rust
代码是很容易实现交叉编译,但是使用到的库中如果使用到C/C++
,编译就会比较复杂,直接运行交叉编译命令如下,可能直接报错
$ cargo build -r --target aarch64-apple-darwin
交叉依赖于项目https://github.com/cross-rs/cross
利用docker
简化了在x86_64
的linux
操作系统上进行交叉编译时所需要的前置设置
安装
$ cargo install cross
该项目需要依赖docker
或者podman
获取镜像的时候由于是直接拉ghcr.io/cross-rs/*
的镜像,所以国内配置的镜像是无法使用的,这个时候需要配置docker
的代理服务才行
查看docker
服务配置文件位置
$ sudo systemctl status docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
依据上面命令输出,修改文件/lib/systemd/system/docker.service
配置HTTP
代理,代理的参数值需要依据自己代理而调整
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:20171"
Environment="HTTPS_PROXY=http://127.0.0.1:20171"
重启服务
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
执行交叉编译
使用的时候需要把cargo
替换为cross
命令
$ cross build -r --target x86_64-pc-windows-gnu
执行的时候会自动拉取一个镜像ghcr.io/cross-rs/x86_64-pc-windows-gnu:{version}
,version
参数的值是默认依据cross
的版本号定的,比如执行命令如下,发现版本号是0.2.5
,则对应的获取镜像是ghcr.io/cross-rs/x86_64-pc-windows-gnu:0.2.5
$ cross --version
cross 0.2.5
[cross] note: Falling back to `cargo` on the host.
cargo 1.68.0 (115f34552 2023-02-26)
编译时候的报错解决
该错误一般会出现在rust
以及第三方库版本非常新,但是cross
的版本是比较久之前发布的
目前cross
的版本是0.2.5
,对应的tag
值也是一样
编译过程当中会出现如下错误,表示找不到某个GLIBC
版本
error: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28' not found (required by /target/release/deps/libfutures_macro-7a167e0564403030.so)
查看容器基础镜像信息
$ docker run ghcr.io/cross-rs/x86_64-pc-windows-gnu:0.2.5 cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.6 LTS (Bionic Beaver)"
...
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
查看支持的GLIBC
版本信息
$ docker run ghcr.io/cross-rs/x86_64-pc-windows-gnu:0.2.5 strings /lib/x86_64-linux-gnu/libc.so.6|grep GLIBC
GLIBC_2.2.5
....
GLIBC_2.24
GLIBC_2.25
GLIBC_2.26
GLIBC_2.27
GLIBC_PRIVATE
GNU C Library (Ubuntu GLIBC 2.27-3ubuntu1.6) stable release version 2.27.
解决步骤
- 切换到项目
https://github.com/cross-rs/cross
的tag v0.2.5
查看文件cross/docker/Dockerfile.x86_64-pc-windows-gnu
发现第一行确实是FROM ubuntu:18.04
- 这个时候浏览器直接访问地址
ghcr.io/cross-rs/x86_64-pc-windows-gnu
,会跳转到https://github.com/cross-rs/cross/pkgs/container/x86_64-pc-windows-gnu
- 发现镜像的
tag
列表当中存在edge
或者main
,镜像很新,对应的是main
分支的镜像,一般使用这种tag
的镜像基本可以解决99%
的GLIBC
版本找不到的问题,虽然不是release
版本的tag
,但是rust
的程序只要可以成功编译出来,就基本不用有什么执行问题的,可以放心使用 在项目根目录下面(与
Cargo.toml
同级)创建一个文件Cross.toml
写入如下[target.x86_64-pc-windows-gnu] image = "ghcr.io/cross-rs/x86_64-pc-windows-gnu:edge"
之后再次执行编译就会使用最新的
edge
镜像了$ cross build -r --target x86_64-pc-windows-gnu
交叉编译苹果系列
下面采用target aarch64-apple-darwin
作为示范
原因
出于版权原因,cross
项目未提供ios/darwin
相关的容器镜像,所以需要自己构建镜像
版权说明查看地址https://github.com/cross-rs/cross-toolchains#apple-targets
cross
还是提供了部分macos/apple
相关的镜像制作的代码,后续所有操作版权问题要自己负责
clone
项目
$ git clone https://github.com/cross-rs/cross
$ cd cross
$ git submodule update --init --remote
其他依赖的仓库
cross
的打包编译苹果的时候需要使用到如下仓库,用来生成macos cross toolchain
和其他一些操作, 该仓库仅作了解
https://github.com/tpoechtrager/osxcross
交叉编译的时候需要传递docker build-arg
参数,MACOS_SDK_DIR和MACOS_SDK_FILE
或者传递一个单独的MACOS_SDK_URL
参数,该参数是苹果的构建包数据信息,这个时候可以选择自己整台MACOS
去获取MACOS_SDK
包,也可以通过第三方仓库获取Macos-sdk
https://github.com/phracker/MacOSX-SDKs
在仓库的release
下查找打包好的sdk
,下面我会使用macos-11.1-sdk
作为MACOS_SDK_URL
的参数
https://github.com/phracker/MacOSX-SDKs/releases/download/11.0-11.1/MacOSX11.1.sdk.tar.xz
修改dockerfile
进入到刚刚的cross
仓库下面,找到文件docker/cross-toolchains/docker/Dockerfile.x86_64-apple-darwin-cross
由于镜像构建过程中会有大量的git clone, curl
等网络操作,国内环境需要配置一下代理,在FROM
下面一行增加代理信息
ENV HTTP_PROXY=http://*****:**
ENV HTTPS_PROXY=http://{IP}:{端口}
修改MACOS_SDK_URL
参数改为
ARG MACOS_SDK_URL="https://github.com/phracker/MacOSX-SDKs/releases/download/11.3/MacOSX11.3.sdk.tar.xz"
docker
组件依赖
交叉编译需要使用到docker buildx
,这个非常重要,是能够打包新cross docker
镜像的关键,由于buildx
还处于实验期,一直不是很稳定,所以需要配置docker
开启该功能
修改~/.docker/config.json
,增加一行
{
...
"experimental": "enabled"
...
}
校验是否启用, 如下,Experimental: true
表示配置成功
$ docker version
Client: Docker Engine - Community
Version: 20.10.17
API version: 1.41
Go version: go1.17.11
Git commit: 100c701
Built: Mon Jun 6 23:02:57 2022
OS/Arch: linux/amd64
Context: default
Experimental: true
检查buildx
版本
$ docker buildx version
github.com/docker/buildx v0.** ***********
开始构建,构建完成之后会生成一个镜像aarch64-apple-darwin-cross:local
$ cargo build-docker-image aarch64-apple-darwin-cross --tag local
如果遇到报错,如下,看提示和建议信息好像是说buildx
未被安装,解决方案也是配置环境变量CROSS_CONTAINER_ENGINE_NO_BUILDKIT=1
不使用buildx
error: failed to solve: rpc error: code = Unknown desc = failed to solve with frontend dockerfile.v0: failed to create LLB definition: unexpected status code [manifests 20.04]: 403 Forbidden
......
Location:
/rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/convert/mod.rs:727
Warning: call to docker failed
Suggestion: is `buildx` available for the container engine?
Note: disable the `buildkit` dependency optionally with `CROSS_CONTAINER_ENGINE_NO_BUILDKIT=1`
这个时候要淡定,不接受他的建议
先尝试去访问buildx
仓库如下,获取最新的一个release
版本
https://github.com/docker/buildx
比如现在获取到的最新的buildx
的下载链接
https://github.com/docker/buildx/releases/download/v0.11.0/buildx-v0.11.0.linux-amd64
下载之后按照buildx
仓库readme
的提示,替换原来的docker-buildx
linux
的docker plugin
的可能位置有
/usr/local/lib/docker/cli-plugins
OR/usr/local/libexec/docker/cli-plugins
/usr/lib/docker/cli-plugins
OR/usr/libexec/docker/cli-plugins
像我的Ubuntu22
机器就是执行如下命令
$ sudo mv buildx-v0.11.0.linux-amd64 /usr/libexec/docker/cli-plugins/docker-buildx
$ sudo chmod a+x /usr/libexec/docker/cli-plugins/docker-buildx
执行完成之后再检查buildx
版本,一般buildx
运行的时候是会遇到很多问题的,该工具也还在实验中,也一直在不断进行更新修复,所以使用最新版本大概率可以解决问题
$ docker buildx version
github.com/docker/buildx v0.11.0 687feca9e8dcd1534ac4c026bc4db5a49de0dd6e
最后再次执行镜像构建
$ cargo build-docker-image aarch64-apple-darwin-cross --tag local
如果还是报错再接受建议,执行命令如下,不使用buildx
$ CROSS_CONTAINER_ENGINE_NO_BUILDKIT=1 cargo build-docker-image aarch64-apple-darwin-cross --tag local
创建Cross.toml
[target.aarch64-apple-darwin]
image = "ghcr.io/cross-rs/aarch64-apple-darwin-cross:local"
执行命令如下就完成交叉编译了
$ cross build --target aarch64-apple-darwin -r
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。