The easiest way to use the NDK in conjunction with this Makefile (tested on linux-x86_64):
1. Download the latest NDK (r21d) from Google from https://developer.android.com/ndk/downloads
2. Place and unzip the NDK in $HOME/ndk folder
3. Export the path variable e.g., `export PATH=$PATH:$HOME/ndk/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64/bin`
4. cd to your Stockfish/src dir
5. Issue `make -j ARCH=armv8 COMP=ndk build` (use `ARCH=armv7` or `ARCH=armv7-neon` for older CPUs)
6. Optionally `make -j ARCH=armv8 COMP=ndk strip`
7. That's all. Enjoy!
Improves support from Raspberry Pi (incomplete?) and compiling on arm in general
closes https://github.com/official-stockfish/Stockfish/pull/3015
fixes https://github.com/official-stockfish/Stockfish/issues/2860
fixes https://github.com/official-stockfish/Stockfish/issues/2641
Support is still fragile as we're missing CI on these targets. Nevertheless tested with:
```bash
# build crosses from ubuntu 20.04 on x86 to various arch/OS combos
# tested with suitable packages installed
# (build-essentials, mingw-w64, g++-arm-linux-gnueabihf, NDK (r21d) from google)
# cross to Android
export PATH=$HOME/ndk/android-ndk-r21d/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH
make clean && make -j build ARCH=armv7 COMP=ndk && make -j build ARCH=armv7 COMP=ndk strip
make clean && make -j build ARCH=armv7-neon COMP=ndk && make -j build ARCH=armv7-neon COMP=ndk strip
make clean && make -j build ARCH=armv8 COMP=ndk && make -j build ARCH=armv8 COMP=ndk strip
# cross to Raspberry Pi
make clean && make -j build ARCH=armv7 COMP=gcc COMPILER=arm-linux-gnueabihf-g++
make clean && make -j build ARCH=armv7-neon COMP=gcc COMPILER=arm-linux-gnueabihf-g++
# cross to Windows
make clean && make -j build ARCH=x86-64-modern COMP=mingw
```
No functional change
Nikolay Kostov (NikolayIT)
Nguyen Pham (nguyenpham)
Norman Schmidt (FireFather)
Nikolay Kostov (NikolayIT)
Nguyen Pham (nguyenpham)
Norman Schmidt (FireFather)
Ondrej Mosnáček (WOnder93)
Oskar Werkelin Ahlin
Pablo Vazquez
Ondrej Mosnáček (WOnder93)
Oskar Werkelin Ahlin
Pablo Vazquez
vnni = no
neon = no
ARCH = x86-64-modern
vnni = no
neon = no
ARCH = x86-64-modern
### 2.2 Architecture specific
### 2.2 Architecture specific
+ifeq ($(ARCH),armv7-neon)
+ arch = armv7
+ prefetch = yes
+ popcnt = yes
+ neon = yes
+ bits = 32
+endif
+
ifeq ($(ARCH),armv8)
arch = armv8-a
prefetch = yes
ifeq ($(ARCH),armv8)
arch = armv8-a
prefetch = yes
CXX=g++
CXXFLAGS += -pedantic -Wextra -Wshadow
CXX=g++
CXXFLAGS += -pedantic -Wextra -Wshadow
- ifeq ($(ARCH),$(filter $(ARCH),armv7 armv8))
+ ifeq ($(arch),$(filter $(arch),armv7 armv8-a))
ifeq ($(OS),Android)
CXXFLAGS += -m$(bits)
LDFLAGS += -m$(bits)
ifeq ($(OS),Android)
CXXFLAGS += -m$(bits)
LDFLAGS += -m$(bits)
LDFLAGS += -m$(bits)
endif
LDFLAGS += -m$(bits)
endif
+ ifeq ($(arch),$(filter $(arch),armv7))
+ LDFLAGS += -latomic
+ endif
+
ifneq ($(KERNEL),Darwin)
LDFLAGS += -Wl,--no-as-needed
endif
ifneq ($(KERNEL),Darwin)
LDFLAGS += -Wl,--no-as-needed
endif
- ifeq ($(ARCH),$(filter $(ARCH),armv7 armv8))
+ ifeq ($(arch),$(filter $(arch),armv7 armv8))
ifeq ($(OS),Android)
CXXFLAGS += -m$(bits)
LDFLAGS += -m$(bits)
ifeq ($(OS),Android)
CXXFLAGS += -m$(bits)
LDFLAGS += -m$(bits)
LDFLAGS += -arch $(arch) -mmacosx-version-min=10.14
endif
LDFLAGS += -arch $(arch) -mmacosx-version-min=10.14
endif
+# To cross-compile for Android, NDK version r21 or later is recommended.
+# In earlier NDK versions, you'll need to pass -fno-addrsig if using GNU binutils.
+# Currently we don't know how to make PGO builds with the NDK yet.
+ifeq ($(COMP),ndk)
+ CXXFLAGS += -stdlib=libc++ -fPIE
+ ifeq ($(arch),armv7)
+ comp=armv7a-linux-androideabi16-clang
+ CXX=armv7a-linux-androideabi16-clang++
+ CXXFLAGS += -mthumb -march=armv7-a -mfloat-abi=softfp -mfpu=neon
+ STRIP=arm-linux-androideabi-strip
+ endif
+ ifeq ($(arch),armv8-a)
+ comp=aarch64-linux-android21-clang
+ CXX=aarch64-linux-android21-clang++
+ STRIP=aarch64-linux-android-strip
+ endif
+ LDFLAGS += -static-libstdc++ -pie -lm -latomic
+endif
+
### Travis CI script uses COMPILER to overwrite CXX
ifdef COMPILER
COMPCXX=$(COMPILER)
### Travis CI script uses COMPILER to overwrite CXX
ifdef COMPILER
COMPCXX=$(COMPILER)
ifneq ($(OS),Android)
# Haiku has pthreads in its libroot, so only link it in on other platforms
ifneq ($(KERNEL),Haiku)
ifneq ($(OS),Android)
# Haiku has pthreads in its libroot, so only link it in on other platforms
ifneq ($(KERNEL),Haiku)
+ ifneq ($(COMP),ndk)
+ LDFLAGS += -lpthread
+ endif
ifeq ($(prefetch),yes)
ifeq ($(sse),yes)
CXXFLAGS += -msse
ifeq ($(prefetch),yes)
ifeq ($(sse),yes)
CXXFLAGS += -msse
endif
else
CXXFLAGS += -DNO_PREFETCH
endif
else
CXXFLAGS += -DNO_PREFETCH
### 3.6 popcnt
ifeq ($(popcnt),yes)
### 3.6 popcnt
ifeq ($(popcnt),yes)
- ifeq ($(arch),$(filter $(arch),ppc64 armv8-a arm64))
+ ifeq ($(arch),$(filter $(arch),ppc64 armv7 armv8-a arm64))
CXXFLAGS += -DUSE_POPCNT
else ifeq ($(comp),icc)
CXXFLAGS += -msse3 -DUSE_POPCNT
CXXFLAGS += -DUSE_POPCNT
else ifeq ($(comp),icc)
CXXFLAGS += -msse3 -DUSE_POPCNT
ifeq ($(avx2),yes)
CXXFLAGS += -DUSE_AVX2
ifeq ($(comp),$(filter $(comp),gcc clang mingw))
ifeq ($(avx2),yes)
CXXFLAGS += -DUSE_AVX2
ifeq ($(comp),$(filter $(comp),gcc clang mingw))
ifeq ($(neon),yes)
CXXFLAGS += -DUSE_NEON
ifeq ($(neon),yes)
CXXFLAGS += -DUSE_NEON
+ ifeq ($(KERNEL),Linux)
+ ifneq ($(COMP),ndk)
+ CXXFLAGS += -mfpu=neon
+ endif
+ endif
endif
ifeq ($(arch),x86_64)
endif
ifeq ($(arch),x86_64)
### needs access to the optimization flags.
ifeq ($(optimize),yes)
ifeq ($(debug), no)
### needs access to the optimization flags.
ifeq ($(optimize),yes)
ifeq ($(debug), no)
+ ifeq ($(COMP),ndk)
+ CXXFLAGS += -flto=thin
+ LDFLAGS += $(CXXFLAGS)
+ else ifeq ($(comp),clang)
CXXFLAGS += -flto=thin
LDFLAGS += $(CXXFLAGS)
CXXFLAGS += -flto=thin
LDFLAGS += $(CXXFLAGS)
endif
# To use LTO and static linking on windows, the tool chain requires a recent gcc:
endif
# To use LTO and static linking on windows, the tool chain requires a recent gcc:
-# gcc version 10.1 in msys2 or TDM-GCC version 9.2 are know to work, older might not.
+# gcc version 10.1 in msys2 or TDM-GCC version 9.2 are known to work, older might not.
# So, only enable it for a cross from Linux by default.
else ifeq ($(comp),mingw)
ifeq ($(KERNEL),Linux)
# So, only enable it for a cross from Linux by default.
else ifeq ($(comp),mingw)
ifeq ($(KERNEL),Linux)
@echo "ppc-64 > PPC 64-bit"
@echo "ppc-32 > PPC 32-bit"
@echo "armv7 > ARMv7 32-bit"
@echo "ppc-64 > PPC 64-bit"
@echo "ppc-32 > PPC 32-bit"
@echo "armv7 > ARMv7 32-bit"
- @echo "armv8 > ARMv8 64-bit"
+ @echo "armv7-neon" > ARMv7 32-bit with popcnt and neon"
+ @echo "armv8 > ARMv8 64-bit with popcnt and neon"
@echo "apple-silicon > Apple silicon ARM64"
@echo "general-64 > unspecified 64-bit"
@echo "general-32 > unspecified 32-bit"
@echo "apple-silicon > Apple silicon ARM64"
@echo "general-64 > unspecified 64-bit"
@echo "general-32 > unspecified 32-bit"
@echo "mingw > Gnu compiler with MinGW under Windows"
@echo "clang > LLVM Clang compiler"
@echo "icc > Intel compiler"
@echo "mingw > Gnu compiler with MinGW under Windows"
@echo "clang > LLVM Clang compiler"
@echo "icc > Intel compiler"
+ @echo "ndk > Google NDK to cross-compile for Android"
@echo ""
@echo "Simple examples. If you don't know what to do, you likely want to run: "
@echo ""
@echo ""
@echo "Simple examples. If you don't know what to do, you likely want to run: "
@echo ""
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) profileclean
strip:
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) profileclean
strip:
install:
-mkdir -p -m 755 $(BINDIR)
install:
-mkdir -p -m 755 $(BINDIR)
@test "$(avx512)" = "yes" || test "$(avx512)" = "no"
@test "$(vnni)" = "yes" || test "$(vnni)" = "no"
@test "$(neon)" = "yes" || test "$(neon)" = "no"
@test "$(avx512)" = "yes" || test "$(avx512)" = "no"
@test "$(vnni)" = "yes" || test "$(vnni)" = "no"
@test "$(neon)" = "yes" || test "$(neon)" = "no"
- @test "$(comp)" = "gcc" || test "$(comp)" = "icc" || test "$(comp)" = "mingw" || test "$(comp)" = "clang"
+ @test "$(comp)" = "gcc" || test "$(comp)" = "icc" || test "$(comp)" = "mingw" || test "$(comp)" = "clang" \
+ || test "$(comp)" = "armv7a-linux-androideabi16-clang" || test "$(comp)" = "aarch64-linux-android21-clang"
$(EXE): $(OBJS)
+$(CXX) -o $@ $(OBJS) $(LDFLAGS)
$(EXE): $(OBJS)
+$(CXX) -o $@ $(OBJS) $(LDFLAGS)