Skip to content

Commit

Permalink
Support building for Android using NDK
Browse files Browse the repository at this point in the history
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 #3015

fixes #2860

fixes #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
  • Loading branch information
notruck authored and vondele committed Aug 18, 2020
1 parent 0e17a89 commit 65b9764
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 10 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Expand Up @@ -127,6 +127,7 @@ Niklas Fiekas (niklasf)
Nikolay Kostov (NikolayIT)
Nguyen Pham (nguyenpham)
Norman Schmidt (FireFather)
notruck
Ondrej Mosnáček (WOnder93)
Oskar Werkelin Ahlin
Pablo Vazquez
Expand Down
65 changes: 55 additions & 10 deletions src/Makefile
Expand Up @@ -102,6 +102,7 @@ avx512 = no
vnni = no
neon = no
ARCH = x86-64-modern
STRIP = strip

### 2.2 Architecture specific

Expand Down Expand Up @@ -208,6 +209,14 @@ ifeq ($(ARCH),armv7)
bits = 32
endif

ifeq ($(ARCH),armv7-neon)
arch = armv7
prefetch = yes
popcnt = yes
neon = yes
bits = 32
endif

ifeq ($(ARCH),armv8)
arch = armv8-a
prefetch = yes
Expand Down Expand Up @@ -251,7 +260,7 @@ ifeq ($(COMP),gcc)
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)
Expand All @@ -261,6 +270,10 @@ ifeq ($(COMP),gcc)
LDFLAGS += -m$(bits)
endif

ifeq ($(arch),$(filter $(arch),armv7))
LDFLAGS += -latomic
endif

ifneq ($(KERNEL),Darwin)
LDFLAGS += -Wl,--no-as-needed
endif
Expand Down Expand Up @@ -311,7 +324,7 @@ ifeq ($(COMP),clang)
endif
endif

ifeq ($(ARCH),$(filter $(ARCH),armv7 armv8))
ifeq ($(arch),$(filter $(arch),armv7 armv8))
ifeq ($(OS),Android)
CXXFLAGS += -m$(bits)
LDFLAGS += -m$(bits)
Expand Down Expand Up @@ -340,6 +353,25 @@ ifeq ($(KERNEL),Darwin)
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)
Expand All @@ -356,7 +388,9 @@ ifneq ($(comp),mingw)
ifneq ($(OS),Android)
# Haiku has pthreads in its libroot, so only link it in on other platforms
ifneq ($(KERNEL),Haiku)
LDFLAGS += -lpthread
ifneq ($(COMP),ndk)
LDFLAGS += -lpthread
endif
endif
endif
endif
Expand Down Expand Up @@ -401,15 +435,14 @@ endif
ifeq ($(prefetch),yes)
ifeq ($(sse),yes)
CXXFLAGS += -msse
DEPENDFLAGS += -msse
endif
else
CXXFLAGS += -DNO_PREFETCH
endif

### 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
Expand All @@ -418,6 +451,7 @@ ifeq ($(popcnt),yes)
endif
endif


ifeq ($(avx2),yes)
CXXFLAGS += -DUSE_AVX2
ifeq ($(comp),$(filter $(comp),gcc clang mingw))
Expand Down Expand Up @@ -462,6 +496,11 @@ endif

ifeq ($(neon),yes)
CXXFLAGS += -DUSE_NEON
ifeq ($(KERNEL),Linux)
ifneq ($(COMP),ndk)
CXXFLAGS += -mfpu=neon
endif
endif
endif

ifeq ($(arch),x86_64)
Expand All @@ -481,7 +520,10 @@ endif
### needs access to the optimization flags.
ifeq ($(optimize),yes)
ifeq ($(debug), no)
ifeq ($(comp),clang)
ifeq ($(COMP),ndk)
CXXFLAGS += -flto=thin
LDFLAGS += $(CXXFLAGS)
else ifeq ($(comp),clang)
CXXFLAGS += -flto=thin
LDFLAGS += $(CXXFLAGS)

Expand All @@ -502,7 +544,7 @@ ifeq ($(debug), no)
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)
Expand Down Expand Up @@ -556,7 +598,8 @@ help:
@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"
Expand All @@ -567,6 +610,7 @@ help:
@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 ""
Expand Down Expand Up @@ -609,7 +653,7 @@ profile-build: net config-sanity objclean profileclean
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) profileclean

strip:
strip $(EXE)
$(STRIP) $(EXE)

install:
-mkdir -p -m 755 $(BINDIR)
Expand Down Expand Up @@ -693,7 +737,8 @@ config-sanity:
@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)
Expand Down

3 comments on commit 65b9764

@gsobala
Copy link
Contributor

@gsobala gsobala commented on 65b9764 Aug 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has broken compilation on armv8 (64-bit) on Raspberry Pi. For AArch64 -mfpu is not a valid option (see developer.arm.com) and is rejected (error) by gcc as an unrecognised option. Pragmatically, -DUSE_NEON is all that is required, although I can find no documentation as to why this should be.

@snicolet
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In you opinion, which part of the commit is the offending part? How could we fix that on your machine?

@vondele
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gsobala can you file an issue, best tracked in that way. Interestingly, this must depend on the toolchain, since the following cross from linux is working:

# cross to RPI
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++

at compile time (I didn't test the binaries).

Please sign in to comment.