3

I was using Eclipse successfully to build Botan using the directions linked to from this question, however, Android Studio is supposed to replace Eclipse for Android development, so I'm trying to get it to build in Android Studio now, but it fails with a missing header file <iosfwd>. I'm getting the following error:

Error:Execution failed for task ':app:compileDebugNdk'.
> com.android.ide.common.internal.LoggedErrorException: Failed to run command:
    /Users/User1/Development/android-ndk-r10d/ndk-build NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=/Users/User1/application1/android/workspace/app/build/intermediates/ndk/debug/Android.mk APP_PLATFORM=android-19 NDK_OUT=/Users/User1/application1/android/workspace/app/build/intermediates/ndk/debug/obj NDK_LIBS_OUT=/Users/User1/application1/android/workspace/app/build/intermediates/ndk/debug/lib APP_ABI=all
  Error Code:
    2
  Output:
    In file included from /Users/User1/application1/android/workspace/app/src/main/jni/botan/botan_all.cpp:8:0:
    /Users/User1/application1/android/workspace/app/src/main/jni/botan/botan_all.h:11:18: fatal error: iosfwd: No such file or directory
     #include <iosfwd>
                      ^
    compilation terminated.
    make: *** [/Users/User1/application1/android/workspace/app/build/intermediates/ndk/debug/obj/local/arm64-v8a/objs/app//Users/User1/application1/android/workspace/app/src/main/jni/botan/botan_all.o] Error 1

Where should I be getting the header file <iosfwd> from and how do I instruct Android Studio to locate it?


Update

I found the following makefile: .../workspace/app/src/main/jni/botan/Android.mk

# jni/botan/Android.mk:
LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := botan
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
LOCAL_SRC_FILES := botan_all.cpp
LOCAL_CPPFLAGS := -DBOTAN_USE_GCC_INLINE_ASM=0

include $(BUILD_SHARED_LIBRARY)

I tried adding the line after LOCAL_CPPFLAGS:

LOCAL_C_INCLUDES := $(ANDROID_STL_INC)

But the build seems unaffected, I get the same error, so I then tried to edit LOCAL_CPPFLAGS to be:

LOCAL_CPPFLAGS := SEE_IF_THIS_BREAKS_THE_BUILD

To see if my edits are being seen, but again, the exact same original failure on header iosfwd. So it appears my edits are not part of the build.

How can I get Android Studio to give more information so I can figure out how it gets to the build step that fails. Presently, when I build, it pauses, then gives window with the error message, but without showing all the intermediate steps to get it there, which might show which makefiles got it to that point.

Community
  • 1
  • 1
WilliamKF
  • 41,123
  • 68
  • 193
  • 295

1 Answers1

1

Where should I be getting the header file from and how do I instruct Android Studio to locate it?

The C++ runtime is not included with --sysroot because it depends on the C++ runtime you want to use.

$ cd /opt/android-ndk-r10
$ find . -name iosfwd
./sources/cxx-stl/gnu-libstdc++/4.6/include/iosfwd
./sources/cxx-stl/gnu-libstdc++/4.8/include/iosfwd
./sources/cxx-stl/llvm-libc++/libcxx/include/iosfwd
./sources/cxx-stl/stlport/stlport/iosfwd
./sources/cxx-stl/stlport/stlport/using/iosfwd

I use STLport because GNU has toxic licensing terms. So here's how STLport looks from the command line and in Eclipse (I know your question is about Android Studio, but this shows how you have to handle the C++ runtime).

So my build script for libraries like Botan (I've actually built and tested it on Android) and Crypto++ have the following:

# If more than one library is using STLport, then all libraries in the
# APK ***must*** use the shared version.
# STLPORT_LIB=libstlport_static.a
STLPORT_LIB=libstlport_shared.so

if [ "$_ANDROID_ARCH" == "arch-arm" ]; then
  if [ "$_ANDROID_ARMV7A" -ne 0 ]; then
      STLPORT_ABI=armeabi-v7a
  else
      STLPORT_ABI=armeabi
  fi
elif [ "$_ANDROID_ARCH" == "arch-x86" ]; then
  STLPORT_ABI=x86
elif [ "$_ANDROID_ARCH" == "arch-mips" ]; then
  STLPORT_ABI=mips
fi

export ANDROID_STL_INC="$ANDROID_NDK_ROOT/sources/cxx-stl/stlport/stlport/"
export ANDROID_STL_LIB="$ANDROID_NDK_ROOT/sources/cxx-stl/stlport/libs/$STLPORT_ABI/$STLPORT_LIB"

Later, the Makefile uses the environmental variables set in the script:

# Android cross-compile configuration. Works in conjunction with IS_CROSS_COMPILE.
#   See http://www.cryptopp.com/wiki/Android_(Command_Line).
ifeq ($(IS_ANDROID),1)
  # CPP, CXX, AR, RANLIB, LD, etc are set in 'setenv-android.sh'
  CXXFLAGS = -DNDEBUG -g2 -Os -pipe -fPIC
  CXXFLAGS += -DCRYPTOPP_DISABLE_ASM $(ANDROID_FLAGS)
  CXXFLAGS += --sysroot=$(ANDROID_SYSROOT) -I$(ANDROID_STL_INC)
  LDLIBS += $(ANDROID_STL_LIB)
endif

And here's how it looks under Eclipse: Compile native C++ shared object with Android NDK. The answer shows the important parts (including Application.mk and Android.mk) of a sample project that provides my C++ shared object, depends on the Crypto++ shared object, and uses libstlport_shared.so.


... how do I instruct Android Studio to locate it...

I don't really have an answer for this because I don't use Android Studio. But it might be helpful to add the following to your build file. It seems to be the standard way of specifying a C++ runtime under Android Studio:

ndk {
    moduleName "MyNativeModule"
    stl "stlport_shared"
    ldLibs "log", "z", "m"
    cFlags "-I/some/include/path"
}

Also see the following:


One important note (from my experience with cross-compiling for Android). Be sure -mfloat-abi=softfp is a compiler option for ARMv7a targets; and -msoft-float is a compiler option for ARMv7 targets. That's important for ABI compatibility.

If -mfloat-abi=softfp is omitted, then floats will be passed incorrectly and the float value that Botan (or other libraries) receive will be 0.0f. OpenSSL suffers this defect - all entropy estimates from Java callers are 0.0f.

Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885