如何将 Stockfish 13 从 windows 10 交叉编译到 armv8?

How to cross-compile Stockfish 13 from windows 10 to armv8?

Stockfish 13, released February 19, 2021, is the strongest chess engine at the moment I am writing these lines. You can download it for windows, linux, mac os, and also android. Yet at the moment I am writing these lines, the android binaries download link points to Stockfish 12 and not 13. (This happens often with Stockfish, as the android binaries are not the ones people need the most.) As Stockfish is open source (github here),我们如何在 windows 10 计算机上为 Android phone 交叉编译 Stockfish 13? (以我为例,三星 Galaxy S21 Ultra 运行 Android 11.)

我们需要源代码:git clone https://github.com/official-stockfish/Stockfish.git(请参阅 Stockfish 的 github 中的正确地址,因为此地址可能会更改)在您 PC 上的某处。 (例如,您需要 Tortois Git 的命令行实用程序。)让我们调用 StockFishDIr PC 上 StockFish 文件夹(包含 src 作为子文件夹)的完整路径。

我们还需要一个交叉编译器来... 将 PC 上的源代码交叉编译 (!) 为可执行文件,目标是 Android OS,意思是:在 ANdroid OS 上可执行,即在 phone 上可执行。我们将使用 Android-NDK,其中包含工具链和交叉编译器。我们下载“Latest Stable Version”r22(截至我写这些行的那一刻)并将其解压缩到 PC 上的一个文件夹中;我在 PC 上将“AndroidNdkDir”称为此目录(包含 buildmetaprebuilttoolchains 等文件夹的完整路径。

最后,由于 Stockfish 的源代码中只有一个 Makefile,我们将需要 windows 下的 make。是的。只需从 GnuWin32 获取它并记下 MakeDir 您 PC 上的安装目录,该目录包含 bin 文件夹,其中包含 make.exe。分析 MakeFile 线性表明,交叉编译归结为只有一个命令行,前提是下载了一些文件,以及另一个“优化”命令行。

现在我们看看 StockFishDIr\src 中的 MakeFile ;我们会稍微修改一下。

首先我们通过更改行

来更改可执行文件的名称
EXE = stockfish

进入

EXE = stockfish_13_armv8_xcomp_win10x64

给它起一个有意义的名字。

其次,我们找到armv8的出现(它是Samsung Galaxy S21 Ultra的ARCH;如果你有另一个Android phone,也许你应该寻找 'armv7' 并因此调整以下内容)关于编译器:即,我们替换位

    ifeq ($(arch),armv8)
        CXX=aarch64-linux-android21-clang++
        STRIP=aarch64-linux-android-strip
    endif

    ifeq ($(arch),armv8)
        CXX=AndroidNdkDir\toolchains\llvm\prebuilt\windows-x86_64\bin\aarch64-linux-android30-clang++.cmd
        STRIP=AndroidNdkDir\toolchains\llvm\prebuilt\windows-x86_64\bin\aarch64-linux-android-strip.exe
endif
    endif

(注意CXX行开头的android21被我替换成了android30。这是因为Samung Galaxy s21 Ultra运行的是Android11,其真实版本号是 android30。如果你有一个 android phone 和另一个 android 版本,相应地调整这些行。)

现在,在编译之前,我们需要最后一个文件:net 文件(技术上,net = networks = neural network = Stockfish 操作的神经网络的权重文件) . “正常”(啊啊),在 linux 设置下(我在这里所做的所有工作几乎 mutatis mutandis 在 Linux 上),我们会做一个 "MakeDir\bin\make.exe" profile-build ARCH=x86-64 它将在需要的地方下载网络文件,我们甚至不会打扰它。遗憾的是,运行 这里"MakeDir\bin\make.exe" profile-build ARCH=x86-64 不知为何不起作用,需要我们自己手动下载net 文件。因此,我们必须在 Makefile 中查看网络文件是如何下载的。 Makefile 中重要的一点是:

# evaluation network (nnue)
net:
    $(eval nnuenet := $(shell grep EvalFileDefaultName evaluate.h | grep define | sed 's/.*\(nn-[a-z0-9]\{12\}.nnue\).*//'))
    @echo "Default net: $(nnuenet)"
    $(eval nnuedownloadurl := https://tests.stockfishchess.org/api/nn/$(nnuenet))
    $(eval curl_or_wget := $(shell if hash curl 2>/dev/null; then echo "curl -skL"; elif hash wget 2>/dev/null; then echo "wget -qO-"; fi))
    @if test -f "$(nnuenet)"; then \
            echo "Already available."; \
        else \
            if [ "x$(curl_or_wget)" = "x" ]; then \
            echo "Automatic download failed: neither curl nor wget is installed. Install one of these tools or download the net manually"; exit 1; \
            else \
            echo "Downloading $(nnuedownloadurl)"; $(curl_or_wget) $(nnuedownloadurl) > $(nnuenet);\
            fi; \
        fi;
    $(eval shasum_command := $(shell if hash shasum 2>/dev/null; then echo "shasum -a 256 "; elif hash sha256sum 2>/dev/null; then echo "sha256sum "; fi))
    @if [ "x$(shasum_command)" != "x" ]; then \
        if [ "$(nnuenet)" != "nn-"`$(shasum_command) $(nnuenet) | cut -c1-12`".nnue" ]; then \
                echo "Failed download or $(nnuenet) corrupted, please delete!"; exit 1; \
            fi \
        else \
            echo "shasum / sha256sum not found, skipping net validation"; \
        fi

我们看到文件的地址是 https://tests.stockfishchess.org/api/nn/$(nnuenet)) 并且变量 nnuenet 是通过 grep 头文件中的字符串 EvalFileDefaultName 定义的 evaluate.h(在 StockFishDIr\src 内),感兴趣的行是:

#define EvalFileDefaultName   "nn-62ef826d1a6d.nnue"

因此变量nnuenet等于字符串“nn-62ef826d1a6d.nnue”,我们要手动下载网络的地址是https://tests.stockfishchess.org/api/nn/nn-62ef826d1a6d.nnue.

当然,这个地址以后可能会变,但是你看这个思路。现在我们把网络文件放在 StockFishDIr\src

现在我们准备交叉编译,在StockFishDIr\src里面执行如下命令:

"MakeDir\bin\make.exe" stockfish_13_armv8_xcomp_win10x64 COMP=ndk COMPCC="AndroidNdkDir\toolchains\llvm\prebuilt\windows-x86_64\bin\aarch64-linux-android30-clang --target=aarch64-linux-android30" ARCH=armv8

(这里也根据你的 Android phone 调整 aarch64-linux-android30 位。)

当前面的命令正确执行时,它会在 StockFishDIr\src 文件夹中生成 stockfish_13_armv8_xcomp_win10x64 二进制文件。这个二进制文件已经可以用在你 phone 上(例如,通过将它放在你的 DroidFish 应用程序的 DroidFish\uci 文件夹中)但不是最佳的,因为大小很大而且执行有点慢。因此,我们必须使用以下命令行“剥离”二进制文件,仍在 StockFishDIr\src 文件夹中:

"AndroidNdkDir\toolchains\llvm\prebuilt\windows-x86_64\bin\aarch64-linux-android-strip" stockfish_13_armv8_xcomp_win10x64

(不再有 android30 但仍然有一个 aarch64 :根据您的 Android phone 在此处也调整 aarch64-linux-android30 位。)

现在,您的二进制文件 stockfish_13_armv8_xcomp_win10x64 完全可以使用了。您可以在 phone 上与 StockFish 13 下棋,然后受苦! ;)