I found that using ndk-build to build an libxxx.so doesn't need -fPIC in LOCAL_CFLAGS. Does that mean that position-independent code isn't necessary for android or that -fPIC is concealed as a default option which you don't need to add again or something else like that? What's the truth?
Related
How might one run an NDK Cmake build independently from the rest of an Android project, ideally from the command line, external to Android Studio?
The equivalent of running ndk-build from the jni directory for slightly older Android NDK projects.
I need to investigate exactly what the calls to the compiler look like, and I can't seem to get this information when building the whole project from within Android Studio
My first attempt was just to run cmake from the project/app directory containing CMakeLists.txt, but this informs me that cmake is not installed - so how is Android Studio managing to build it then?
If your goal is to just run from the command line (as opposed to trying to do exactly what gradle is doing), just use cmake the way you normally would:
$ cmake -DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=whatever $YOUR_SOURCE_DIR
Alternatively, you can just run ./gradlew from the command line.
Your original problem is that you cannot see the command-line invocation when building with Android Studio.
You can get the command line arguments to the compiler by editing your app/build.gradle file.
defaultConfig {
...
externalNativeBuild {
cmake {
...
arguments "-DCMAKE_VERBOSE_MAKEFILE=1", ...
}
}
}
In Adroid Studio's Gradle Console pane, you will then see the command line for the compiler and linker like so:
[1/176] /home/bram/android-sdk-linux/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin/clang --target=armv7-none-linux-androideabi --gcc-toolchain=/home/bram/android-sdk-linux/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64 --sysroot=/home/bram/android-sdk-linux/ndk-bundle/sysroot -isystem /home/bram/android-sdk-linux/ndk-bundle/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=19 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -fno-integrated-as -marm -mfpu=neon -Wa,--noexecstack -Wformat -Werror=format-security -Os -DNDEBUG -fPIC -MD -MT /home/bram/src/GPGOAP/CMakeFiles/gpgoap.dir/astar.c.o -MF /home/bram/src/GPGOAP/CMakeFiles/gpgoap.dir/astar.c.o.d -o /home/bram/src/GPGOAP/CMakeFiles/gpgoap.dir/astar.c.o -c /home/bram/src/GPGOAP/astar.c
As detail to the accepted answer:
The complete set of parameters passed to CMake is written to:
<project-root>/<module-root>/.externalNativeBuild/cmake/<build-type>/<ABI>/cmake_build_command.txt`
See for details: https://developer.android.com/ndk/guides/cmake.html#build-command
I am compiling a set of several C++ libraries to arm-v7a using the Android NDK on Windows. I am compiling using ndk-build, for the most part. However, one of the libraries I am using (let's call it libproblem.so) has a rather complex makefile, so I use the ajb-tools (https://subversion.assembla.com/svn/ajb-tools/trunk/android/android-cross/android-cross) to call the makefile to build just that library on Linux. Both of these use the same NDK version.
I've made a few changes to the defaults in the android-cross script, to match my Application.mk, including:
export ANDROID_GCCVER=${ANDROID_GCCVER-4.8}
export ANDROID_PLAT_API_VER=${ANDROID_PLAT_API_VER-10} #not sure what this does...
export ANDROID_PLAT_NDK_VER=${ANDROID_PLAT_NDK_VER-9} #gingerbread
export ANDROID_TUNE=${ANDROID_TUNE-"-mandroid $ANDROID_TUNE_THUMB -mthumb-interwork -Wno-psabi -fpic -funwind-tables -fstack-protector -march=armv7-a -finline-limit=64"}
This seems to work fine, and gives me a library whose output to file gives me this:
../obj/local/armeabi-v7a/libproblem.so: ELF 32-bit LSB shared object, ARM,
version 1 (SYSV), dynamically linked (uses shared libs), not stripped
I am then linking it with the other libraries using the following in my Makefile.mk.
include $(CLEAR_VARS)
LOCAL_MODULE := problem
LOCAL_SRC_FILES := $(JNI_PATH)/../libs/prebuilt/$(TARGET_ARCH_ABI)/libproblem.so
include $(PREBUILT_SHARED_LIBRARY)
However, this causes a linking error. The library that depends on libproblem fails to create a shared object, stating:
d:/Code/project/jni/SomeCode.cpp:191: error: undefined reference to 'Problem::Client::Client(std::shared_ptr<Problem::Data> const&)'
The function of course exists. If I run nm on the libproblem.so in MinGW, I see the function there (albeit mangled).
My only line of thought currently is that there is an issue using two different Host OSes. Because what is particularly strange, is that ndk-build links libproblem.so with the rest of my objects succesfully if I use linux as the host OS for running ndk-build. (Keep in mind both Linux and Windows have the same NDK version, NDKr10b, 32-bit target for 64-bit host).
Or have I missed something in the android-cross script that is building that library in a way that's incompatible with my version of ndk-build?
UPDATE: The linking command that fails is as follows.
/c/Android/android-ndk-r10b/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-
x86_64/bin/arm-linux-androideabi-g++ -Wl,-soname,libFinal.so -shared
--sysroot=c:/Android/android-ndk-r10b/platforms/android-9/arch-arm d:/Code/project
/obj/local/armeabi-v7a/objs/Final/Final.o d:/Code/project/jni/../libs/prebuilt/
armeabi-v7a/libboost_system.a d:/Code/project/jni/../libs/prebuilt/armeabi-
v7a/libboost_date_time.a d:/Code/project/jni/../libs/prebuilt/armeabi-
v7a/libboost_filesystem.a -lgcc d:/Code/project/obj/local/armeabi-v7a/
lib1noproblem.so d:/Code/project/obj/local/armeabi-v7a/lib2noproblem.so d:/Code/
project/obj/local/armeabi-v7a/libproblem.so d:/Code/project/obj/local/armeabi-
v7a/libgnustl_shared.so -no-canonical-prefixes -march=armv7-a -Wl,--fix-cortex-a8
-Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Lc:/Android/
android-ndk-r10b/platforms/android-9/arch-arm/usr/lib -lm -llog c:/Android/
android-ndk-r10b/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/libsupc++.a
-lc -lm -o d:/Code/project/obj/local/armeabi-v7a/libFinal.so
It would be useful if you could show the final link command and the full error message that it generates. Order of libraries is important when linking ELF libraries, and the undefined reference could come from that.
use 'ndk-build V=1' to dump the build commands.
I have some open source library files in my project (e.g: http://nothings.org/stb_vorbis/stb_vorbis.c). -Wall option is enabled in my Android.mk file. During compilation several warnings are generated in stb_vorbis.c.
warning: unused variable <var>
warning: statement with no effect
warning: <var> defined but not used
warning: <var> may be used uninitialized in this function
For some reason I do not want to modify stb_vorbis.c but still want the -Wall option to be available for my own source files. Is there any way to disable -Wall option for specific files/folder ?
Is there any way to disable -Wall option for specific files/folder ?
I do not believe there is any gcc option that could be used to achieve this. You need to change your Makefile that you used to compile the problematic source files.
You could do something like
CFLAGS:=$(filter-out -Wall, $(CFLAGS))
in the Makefile for stb_vorbis, if your make supports filter-out function.
Also you could write a specific rule for that stb_vorbis.c:
STB_VOBIS_CFLAGS:=$(filter-out -Wall, $(CFLAGS))
stb_vorbis.o: stb_vorbis.c ...
$(CC) $(STB_VOBIS_CFLAGS) -o $# -c $<
Although there's no way to turn off -Wall with one option, you can turn off specific warnings in GCC, using the -Wno-* for warning *. So, for example, to suppress the unused variable warning you can add -Wno-unused-variable. See http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html for more information on different warning options.
So for example you could use target-specific variables, like:
stb_vorbis.c: CFLAGS += -Wno-unused-variable
Using target-specific variables you can append the -w option to inhibit all warning messages for stb_vorbis.c file:
stb_vorbis.o: CFLAGS += -w
or for an entire directory:
third_party/%.o: CFLAGS += -w
A general rule of thumb is that if you have two or more mutually exclusive options, gcc will generally take later options over earlier ones.
using -isystem was the working solution for me.
For example, instead of -IC:\\boost_1_52_0, say -isystem C:\\boost_1_52_0.
Described in detail in the following thread:
How do you disable the unused variable warnings coming out of gcc in 3rd party code I do not wish to edit?
Thank you #lee-duhem for your kind and useful suggestions.
We noticed that some dead functions are not removed from the generated shared object file (.so) that is built as release (via "ndk-build" without any parameter).
To prove that we introduced a dummy function that is definitely not called anywhere (and is also not exported since the default visibility is already set to "hidden" for the whole .so). Somehow the symbol of the dummy function still exists and we can see it by using "nm" against the generated .so.
We are using NDK r8d on Linux 11.10.
Is there any specific compiler/linker flags that we need to apply to Android.mk in order to get the dead code removed?
Thank you!
Removing dead functions can greatly reduce the binary size too. For this, change C and C++ compilation flags and the linker flags in Android.mk.
LOCAL_CPPFLAGS += -ffunction-sections -fdata-sections
LOCAL_CFLAGS += -ffunction-sections -fdata-sections
LOCAL_LDFLAGS += -Wl,--gc-sections
Also, the visibility features in GCC can be of help.
http://gcc.gnu.org/wiki/Visibility
I am trying to use the Android NDK on Mountain Lion to build a library for Android, following this guide
http://masl.cis.gvsu.edu/2012/01/25/android-echoprint/
When it comes time to compile the library, I run:
cd <path to jni>
<ndk>/ndk-build
I get the following error:
Compile++ thumb : echoprint-jni <= AndroidCodegen.cpp
arm-linux-androideabi-g++: error trying to exec 'cc1plus': execvp: No such file or directory
make: *** [/Users/wingdom/Desktop/obj/local/armeabi/objs/echoprint-jni/AndroidCodegen.o] Error 1
I believe I have added everything I need to to my path variable:
export PATH=$PATH:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:Developer/android-sdk/tools:/Developer/android-sdk/platform-tools:/Developer/android-ndk:/Developer/android-ndk/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86/bin
What else do I need to do in order to get this to compile? I am using the r8b NDK currently, but have tried it with versions all the way back to 6.
EDIT:
I tried this solution: Error while building android ndk sample project
adding
export PATH=$PATH:/usr/lib/i386-linux-gnu/gcc/i686-linux-gnu/4.5.2
to my path gets me this error:
cc1plus: error: unrecognized command line option "-mbionic"
cc1plus: error: unrecognized command line option "-mthumb"
cc1plus: error: unrecognized command line option "-mfpu=vfp"
/Users/wingdom/Desktop/jni/AndroidCodegen.cpp:1: error: bad value (armv5te) for -march= switch
/Users/wingdom/Desktop/jni/AndroidCodegen.cpp:1: error: bad value (xscale) for -mtune= switch
make: *** [/Users/wingdom/Desktop/obj/local/armeabi/objs/echoprint-jni/AndroidCodegen.o] Error 1
but adding
export CROSS_COMPILER=$PATH:/Developer/android-ndk/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86/bin
doesn't help, like it did in the link above.
I have experienced same error.
I was not able to execute even 'gcc, g++' command. So I have googled a lot to find solution, but nothing helped for me.
Then, I found that some filename in ndk is not correct, with tailing _ on some filename.. (In my case, in toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86/arm-linux-androideabi/bin folder, there are gcc_, g++_, c++_ instead of gcc, g++, c++.)
I used The unarchiver to extract NDK archive, so I think there are something wrong with unarchiving procedure.
So I re-downloaded NDK and checked MD5 checksum, then extracted archive using Mac's default archive utility.
Now, the problem has solved.
Sounds like you have a bad download/unpack of the NDK. The cc1plus binary that it's looking for should be in $NDK_HOME/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/libexec/gcc/arm-linux-androideabi/4.4.3/. If it's not there, try re-downloading the SDK and/or unpacking it again.
If it is there, be sure to build passing V=1 to ndk-build, and see if there are any odd -B options passed to the compiler. The -B option tells gcc where to find its "sub-programs" (of which cc1plus is one). Pretty sure there shouldn't be any on the command lines for r8, so if there are, something somewhere is passing bad flags. For example, on my system, a C++ NDK command line ends up looking something like this:
/opt/android-ndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-g++ -MMD -MP -MF ./obj/local/armeabi-v7a/objs/sometarget/SomeCppFile.o.d -fpic -ffunction-sections -funwind-tables -fstack-protector -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -Wno-psabi -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -fno-exceptions -fno-rtti -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -I/opt/android-ndk/sources/cxx-stl/stlport/stlport -I/opt/android-ndk/sources/cxx-stl//gabi++/include -DANDROID -Wall -Wa,--noexecstack -frtti -O2 -DNDEBUG -g -I/opt/android-ndk/platforms/android-8/arch-arm/usr/include -c jni/SomeCppFile.cpp -o ./obj/local/armeabi-v7a/objs/sometarget/SomeCppFile.o
Maybe you need to install the g++:
$sudo apt-get install g++
I have spent about a day to find root cause of this
arm-linux-androideabi-gcc: error trying to exec 'cc1': execvp: No such file...
and others issues.
The issues were that I unpacked NDK and SDK with 7z which removed executable permission for all binaries and Eclipse was not able to start cc1.
Once I unpacked tar files of SDK and NDK using tar, everything started working well.