如何在Windows上为FastAPI项目交叉编译多平台二进制文件?

如何在Windows上进行python项目(fastapi框架)交叉编译,编译linux-amd64,linux-arm64,mac多平台二进制文件?

我试过在github action编译,但是无法编译linux-ARM64的软件包,只能编译linux-amd64的。

我的需求:
1,github action如何编译linux-arm64的二进制程序?
2,在Windows上安装docker desktop软件,如何在这个软件内进行编译多平台程序?【生产环境代码不变上传github】
以下是github action编译的arm64,但是运行发现仍然是amd64的:

[root@lnas552f ~]# ./fastapi_app
-sh: ./fastapi_app: cannot execute binary file: Exec format error
[root@lnas552f ~]# file ./fastapi_app
./fastapi_app: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=aa5cd8892ec75e94945edf5de21c0673ae51ac17, for GNU/Linux 2.6.32, stripped

我的action workflow.yml如下:

name: Build and Release ARM64 Binary

on:
  push:
    tags:
      - v*

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Set up Python 3.11
        uses: actions/setup-python@v3
        with:
          python-version: "3.11"

      - name: Install dependencies
        run: |
          sudo apt-get update
          sudo apt-get install -y gcc-aarch64-linux-gnu
          pip install fastapi pyinstaller pywebview uvicorn

      - name: Build ARM64 executable
        env:
          CFLAGS: "-march=armv8-a"
          CC: aarch64-linux-gnu-gcc  # 指定交叉编译器
        run: |
          pyinstaller --onefile --name fastapi_app app.py
          file ./dist/fastapi_app  # 确认文件类型

      - name: Create release if needed
        id: create_release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ github.ref }}
          release_name: "Release ${{ github.ref }}"
          body: "Release for Linux ARM64"
          draft: false
          prerelease: false

      - name: Upload ARM64 binary to release
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./dist/fastapi_app
          asset_name: fastapi_app-arm64
          asset_content_type: application/octet-stream
阅读 790
avatarAI BotBETA

回答

1. 在 GitHub Actions 中编译 Linux-ARM64 的二进制程序

问题出在你的 pyinstaller 配置上。pyinstaller 默认不会使用你设置的 CC 环境变量来编译二进制文件。你需要显式地告诉 pyinstaller 使用正确的交叉编译工具链。

你可以通过修改 pyinstaller.spec 文件或者使用命令行参数来指定交叉编译工具链。不过,对于 pyinstaller,直接指定交叉编译工具链的支持有限,通常建议使用 Docker 或其他容器化技术来确保编译环境的一致性。

但是,如果你仍然想在 GitHub Actions 中直接处理,可以尝试以下步骤:

  1. 确保安装了正确的交叉编译工具链:你已经安装了 gcc-aarch64-linux-gnu,这是正确的。
  2. 修改 .spec 文件或使用命令行参数

    • 创建一个 .spec 文件,并在其中指定 binarydatas 的路径,同时确保 hookspathruntime_hooks 指向正确的位置(如果需要)。
    • .spec 文件中,你可以尝试设置 a.binariesa.zipfiles 的路径,以确保它们使用正确的编译器和链接器。不过,这通常比较复杂且容易出错。
  3. 使用 Docker:这是更推荐的方法,因为它可以提供一个干净、一致的环境,避免直接在 GitHub Actions 环境中处理复杂的交叉编译问题。

2. 在 Windows 上使用 Docker Desktop 编译多平台程序

使用 Docker 是在 Windows 上编译多平台二进制文件的最佳实践之一。以下是如何在 Docker 中进行交叉编译的步骤:

  1. 安装 Docker Desktop:确保你已经安装了 Docker Desktop,并且可以从命令行访问 docker 命令。
  2. 创建 Dockerfile:为每个目标平台创建一个 Dockerfile。例如,为 Linux-AMD64、Linux-ARM64 和 macOS 创建不同的 Dockerfile。
  3. 编写 Docker 构建脚本:编写一个脚本(如 build.sh),该脚本使用 Docker 构建每个平台的镜像,并在其中编译你的 FastAPI 应用。
  4. 运行构建脚本:在 Windows 上运行你的构建脚本,它将使用 Docker 来构建和编译你的应用。
  5. 上传构建结果到 GitHub:将编译好的二进制文件上传到 GitHub,作为发布资产。

下面是一个简单的 Dockerfile 示例,用于编译 Linux-ARM64 的 FastAPI 应用:

# 使用官方的 Python 镜像作为基础镜像
FROM python:3.11-slim-buster AS build

# 设置工作目录
WORKDIR /app

# 复制当前目录的内容到工作目录
COPY . .

# 安装依赖
RUN pip install --no-cache-dir -r requirements.txt

# 安装 pyinstaller
RUN pip install --no-cache-dir pyinstaller

# 编译应用
RUN pyinstaller --onefile --name fastapi_app app.py

# 创建一个新的阶段来复制编译好的二进制文件
FROM alpine:latest AS final

# 复制编译好的二进制文件到新的镜像中
COPY --from=build /app/dist/fastapi_app /usr/local/bin/fastapi_app

# 设置执行权限
RUN chmod +x /usr/local/bin/fastapi_app

# 设置入口点
ENTRYPOINT ["/usr/local/bin/fastapi_app"]

然后,你可以使用 Docker 构建和运行这个镜像,确保它正确编译了 ARM64 的二进制文件。

希望这些信息能帮助你解决问题!

1 个回答

编译多平台二进制文件通常有两种方案:

  1. 交叉编译
  2. 多平台编译

github actions将在年底推出面向公共项目的 aarch64 的 runner 实例,到时候方案二会更方便 (目前只有组织用户和企业用户可用,如果你是这两种用户,那么你现在就可以采用这种方案,而不需要下面的qemu方案)。不过目前你可以考虑采用 qemu 模拟 CPU 指令的方案实现类多平台编译的效果。正好,docker就支持 qemu。

详情可以看看 docker 官方 blog 的描述,非常建议一阅: https://www.docker.com/blog/faster-multi-platform-builds-dock...

利用 docker 的 cross platform 特性 (基于 Qemu 实现)就可以轻松实现一套编译脚本支持多平台构建了,一个示例可以参考我的github action,利用此特性构建多平台安装包: https://github.com/abcfy2/docker-postgresql-dev-packages

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏