Issue
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), how could we cross-compile Stockfish 13 on a windows 10 computer for an Android phone ? (In my case, a Samsung Galaxy S21 Ultra running Android 11.)
Solution
We are going to need the source code : git clone https://github.com/official-stockfish/Stockfish.git
(see the right address at Stockfish's github as this address could change) somewhere on your PC. (You need the command line utilities of Tortois Git for instance.) Let's call StockFishDIr
the full path to the StockFish folder (that contains src
as subfolder) on the PC.
We also need a cross-compiler to ... cross-compile (!) the source-code on the PC into an executable targeting the Android OS, meaning : being executable on the ANdroid OS, i.e. on the phone. We are going to use Android-NDK, which contains toolchains and cross-compilers. We download the "Latest Stable Version" r22 (as of the moment I am writing these lines) and unzip it to a folder on the PC ; I call "AndroidNdkDir" the full path to this directory (containing build
, meta
, prebuilt
, toolchains
etc folders) on the PC.
Finally, as in Stockfish's source code there is only a Makefile, we are going to need make
under windows. Yes. Just get it from GnuWin32 and note MakeDir
the installation directory on you PC, the one containg the bin
folder containing make.exe
. Analyzing the MakeFile
linearly show that the cross-compilation boils down to only one command line provided some file is downloaded, and to another "optimizing" command line.
Now we look at the MakeFile
from StockFishDIr\src
; we will modify it slightly.
First we change the executable name by changine the line
EXE = stockfish
into
EXE = stockfish_13_armv8_xcomp_win10x64
to give it a meaningful name.
Second, we locate the occurence of armv8
(it is the ARCH
of the Samsung Galaxy S21 Ultra ; if you have another Android phone, maybe you should look for 'armv7' and adapt consequently what follows) concerning the compiler : namely, we replace the bit
ifeq ($(arch),armv8)
CXX=aarch64-linux-android21-clang++
STRIP=aarch64-linux-android-strip
endif
with
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
(Note that there was the initial android21
in the CXX line that I replaced with android30
. It is because the Samung Galaxy s21 Ultra runs Android 11 whose real version number is android30. If you have an android phone with another android version, adapt the lines consequently.)
Now, before compiling, we need one last piece : the net file (technical, net = networks = neural network = the weights file of the neural network Stockfish operates with). "Normally" (ah ah), under a linux setup (all what I do here works almost mutatis mutandis on Linux), we would just do a "MakeDir\bin\make.exe" profile-build ARCH=x86-64
which would download the net file where needed, and we would not even bother we it. Sadly, running here "MakeDir\bin\make.exe" profile-build ARCH=x86-64
doesn't work for some reason, and we need to download the net file ourselves manually. Hence we have to look in the Makefile to find how the net file is downloaded. The bit that matters in the Makefile is :
# evaluation network (nnue)
net:
$(eval nnuenet := $(shell grep EvalFileDefaultName evaluate.h | grep define | sed 's/.*\(nn-[a-z0-9]\{12\}.nnue\).*/\1/'))
@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
We see that the address of the file is https://tests.stockfishchess.org/api/nn/$(nnuenet))
and that the variable nnuenet
is defined by grep
ing the string EvalFileDefaultName
inside the header file evaluate.h
(which is inside StockFishDIr\src
), the line of interest being :
#define EvalFileDefaultName "nn-62ef826d1a6d.nnue"
Hence the variable nnuenet
is equal to the string "nn-62ef826d1a6d.nnue" and the address we are going to download the nets from manually is https://tests.stockfishchess.org/api/nn/nn-62ef826d1a6d.nnue.
Of course, this address may change in the future, but you see the idea. Now we place the net file inside StockFishDIr\src
Now we are ready to cross-compile, with the following command to execute inside 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
(Adapt here also the aarch64-linux-android30
bits according to your Android phone.)
When the preceeding command executes properly it produces the stockfish_13_armv8_xcomp_win10x64
binary inside the StockFishDIr\src
folder. This binary is already usuable on you phone (by putting it inside the DroidFish\uci
folder of your DroidFish app, for instance) but is not optimal as the size is big and the execution is a little bit slow. Hence we have to "strip" the binary with the following command line, still inside the StockFishDIr\src
folder :
"AndroidNdkDir\toolchains\llvm\prebuilt\windows-x86_64\bin\aarch64-linux-android-strip" stockfish_13_armv8_xcomp_win10x64
(There's no android30
anymore but there is still a aarch64
: adapt here also the aarch64-linux-android30
bits according to your Android phone.)
Now, your binary file stockfish_13_armv8_xcomp_win10x64
is perfectly usable. You can play chess against StockFish 13 on your phone, and suffer ! ;)
Answered By - Olorin
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.