Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Build issue when using <cmath> with android ndk

I have a simple file stlTest2.cpp like this:

#include <jni.h>

#include <cmath>


bool isnan (void);

There is something more complicated in some code I am porting. My question is this. Why would this work when building using GCC outside of the NDK, but not with using the NDK? There error it gives is this:

jni/stlTest2.cpp:6: error: expected unqualified-id before 'sizeof'
jni/stlTest2.cpp:6: error: expected ')' before 'sizeof'

The immediate reason for this is that math.h (included via <cmath>) defines isnan as a macro. Why is the build outside of the ndk not including the #define from math.h, but this is? If I comment out the includes in the code, all is fine, but that is not acceptable as this problem repeats itself.... a lot.

like image 285
corbin Avatar asked Jan 07 '12 00:01

corbin


People also ask

What is NDK-build Android?

The Android Native Development Kit (NDK): a set of tools that allows you to use C and C++ code with Android. CMake: an external build tool that works alongside Gradle to build your native library. You do not need this component if you only plan to use ndk-build.

How do you compile with NDK?

To have the ndk-build script build an application, first create a project folder. In the folder, create a folder named jni. In the jni folder, place the Android.mk file, Application.mk file, and source files. Then navigate to the project folder in a terminal and execute ndk-build.

Where is Android toolchain CMake?

The CMake toolchain file The toolchain file used for the NDK is located in the NDK at <NDK>/build/cmake/android.


2 Answers

The isnan macro was added in C99. In C++11 it was added as a function in the std namespace, overloaded for float and double and long double (so a typical <cmath> header, such as your non-NDK GCC is probably using, might have something like this:

#undef isnan

inline bool isnan(float ...) { ... }

inline bool isnan(double ...) { ... }

inline bool isnan(long double ...) { ... }

), but apparently the NDK hasn't gotten the memo, and is still providing the C99 macro as a convenience. (isnan was never a macro in C++, but before TR1 added std::tr1::isnan, there wasn't really a C++ alternative, so multiple C++ compilers provided the C99 macro.)

Do you need to be able to use the compiler-provided isnan or std::isnan? If not, then you can just change this:

#include <cmath>

to this:

#include <cmath>

#undef isnan

(and similarly for any other problematic macros, provided you don't need them).

like image 134
ruakh Avatar answered Oct 17 '22 07:10

ruakh


In $ndk\sources\cxx-stl\gnu-libstdc++\libs\armeabi\include\bits\c++config.h (change armeabi to whatever is appropriate) change this:

/* #undef _GLIBCXX_USE_C99_MATH */

to

#define _GLIBCXX_USE_C99_MATH 1

Then clean and build your project again.

like image 39
corbin Avatar answered Oct 17 '22 07:10

corbin