1. Some C++11 features are used in IoTivity. Old Android NDK may doesn't
support a part of these features directly. Implement and include it if
it is required.
2. Fix libc function missing problem. Some functions, e.g. rand, srand.
strtof ... are static inline prior to android-L(it is defined and
implemented in the header file). So before android-L libc.so doesn't
include them. If build on android-L and run on an old platform(earlier
than android-L), there will be 'can't locate xxx' problem.
e.g.:
rand, it is defined in stdlib.h as "static __inline__ int rand() { ....} in
the ndk < 10. it's defined as 'extern int rand();' from ndk-10x. With old
ndk, if a file (x.c) used 'rand' function, when build x.c, 'rand' is compiled
into x.o. 'rand' won't exit in neither libc.so nor libc.a. If build an
application with ndk-10x and run it on emulator or device(developed with
NDK < 10), it requires implement 'rand' function by owerself or there
will be be 'can't locate rand' problem.
For convenience, add these functions in a file, if necessary, build it as
library and auto link into binary.
Change-Id: If47da94db7d06fde9887eba335bc0c67762514a9
Signed-off-by: Caiwen Zhang<caiwen.zhang@intel.com>
(cherry picked from commit
f56a9ad5a7c86609cf8895e8a579fb192f0ebfdb)
Reviewed-on: https://gerrit.iotivity.org/gerrit/175
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Sudarshan Prasad <sudarshan.prasad@intel.com>
# Android build system default cofig
env.AppendUnique(CPPDEFINES = ['ANDROID'])
-env.AppendUnique(CFLAGS = ['-Wa,--noexecstack'])
-env.AppendUnique(CXXFLAGS = ['-Wa,--noexecstack', '-fstack-protector'])
+env.AppendUnique(SHCFLAGS = ['-Wa,--noexecstack'])
env.AppendUnique(LINKFLAGS = ['-Wl,--gc-sections', '-Wl,-z,nocopyreloc'])
######################################################################
target_arch = env.get('TARGET_ARCH')
-# Android ndk early version doesn't support C++11. Detect the toolchain
-# and platform version to make sure the newest version is used.
-
-# Detect toolchain version
-for tc_ver in ['4.9', '4.8', '4.7', '']:
- if os.path.exists(android_ndk + '/sources/cxx-stl/gnu-libstdc++/' + tc_ver):
+# Android ndk early version doesn't support C++11. Detect the toolchain version
+# to make sure proper toolchain is used
+for tc_ver in ['4.7', '4.8', '4.9', '']:
+ if os.path.exists(android_ndk + '/toolchains/x86-' + tc_ver):
break
-# Detect platform version.
-platform_ver = ''
-for pf_ver in range(0, 100): # 100 should be big enough :)
- if os.path.exists(android_ndk + '/platforms/android-%d' % pf_ver):
- platform_ver = "%d" % pf_ver
-
cmd = [ndk_build_cmd]
cmd.append('APP_ABI=' + target_arch)
cmd.append('APP_STL=gnustl_static')
*******************************************************************************
'''
-if platform_ver != '':
- cmd.append('APP_PLATFORM=android-' + platform_ver)
cmd.append('-n')
p = subprocess.Popen(cmd, stdout = subprocess.PIPE)
sysroot = flags[8:].strip()
env.AppendUnique(LINKFLAGS = ['--sysroot=' + sysroot])
env.AppendUnique(LIBPATH = [sysroot + '/usr/lib'])
- # To fix android NDK issue
- # Some functions, e.g. rand, srand. strtof ... are static in static inline
- # prior to android-L. so libc.so before android-L doesn't have them. If build
- # build on android-L and the function(s) is used, should link libc.a
- if platform_ver == '' or int(platform_ver) > 20:
- env.AppendUnique(LIBS = File(sysroot + '/usr/lib/libc.a'))
elif cmp(flags[0:8], 'LDFLAGS=') == 0:
env.AppendUnique(LINKFLAGS = Split(flags[8:]))
env.AppendUnique(LIBPATH = [android_ndk + '/sources/cxx-stl/gnu-libstdc++/'
+ ver + '/libs/' + target_arch])
+ elif cmp(flags[0:9], 'PLATFORM=') == 0: # get target platform: android-x
+ platform_ver = flags[9+8:].strip()
+ if not platform_ver.isdigit():
+ platform_ver = ''
+
######################################################################
# Set release/debug flags
######################################################################
env.AppendUnique(LINKFLAGS = ['-s'])
else:
env.AppendUnique(CCFLAGS = ['-g'])
+
+# From android-5 (API > 20), all application must be built with flags '-fPIE' '-pie'.
+# Due to the limitation of Scons, it's required to added it into the command line
+# directly (otherwise, it will also be added when build share library)
+env.Replace(CCCOM = '$CC -o $TARGET -c $CFLAGS $CCFLAGS $_CCCOMCOM -fPIE $SOURCES')
+env.Replace(CXXCOM = '$CXX -o $TARGET -c $CXXFLAGS $CCFLAGS $_CCCOMCOM -fPIE $SOURCES')
+env.Replace(LINKCOM = '$LINK -o $TARGET -pie $LINKFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS')
+
+# Fix android-ndk compatibility issue, make applications build on new NDK can run on old platform
+if platform_ver == '' or int(platform_ver) > 20:
+ SConscript('compatibility/c_compat.scons')
+
+SConscript('compatibility/cpp11_compat.scons')
--- /dev/null
+#include <sstream>
+#include "android_cpp11_compat.h"
+
+namespace OC {
+ template <typename T>
+ void from_string(const std::string& s, T& result) {
+ std::stringstream ss(s);
+ ss >> result; // TODO handle errors
+ }
+}
+
+namespace std {
+
+ int stoi(const string& s)
+ {
+ int ret;
+ int &ref = ret;
+ OC::from_string(s, ref);
+ return ret;
+ }
+
+ double stod(const std::string& s)
+ {
+ double ret;
+ double &ref = ret;
+ OC::from_string(s, ref);
+ return ret;
+ }
+
+ long long stoll(const std::string& s)
+ {
+ long long ret;
+ long long int &ref = ret;
+ OC::from_string(s, ref);
+ return ret;
+ }
+
+ unsigned long long stoull(const std::string& s)
+ {
+ unsigned long long ret;
+ unsigned long long &ref = ret;
+ OC::from_string(s, ref);
+ return ret;
+ }
+
+ long double stold(const string& s)
+ {
+ long double ret;
+ long double &ref = ret;
+ OC::from_string(s, ref);
+ return ret;
+ }
+
+ std::string to_string(int t) {
+ std::ostringstream os;
+ os << t;
+ return os.str();
+ }
+
+ std::string to_string(double t) {
+ std::ostringstream os;
+ os << t;
+ return os.str();
+ }
+
+ std::string to_string(uint32_t t)
+ {
+ std::ostringstream os;
+ os << t;
+ return os.str();
+ }
+
+} // std
--- /dev/null
+#ifndef _ANDRDIO_STRING_H_
+#define _ANDRDIO_STRING_H_
+
+#ifdef __ANDROID__
+#include <string>
+
+#ifndef ANDROID_C11_COMPAT
+using std::to_string;
+#else
+namespace std {
+ int stoi(const std::string& s);
+ double stod(const std::string& s);
+ long long stoll(const std::string& s);
+ unsigned long long stoull(const std::string& s);
+ long double stold(const string& s);
+
+ std::string to_string(int i);
+ std::string to_string(uint32_t i);
+ std::string to_string(double d);
+}
+#endif
+
+#endif
+
+#endif
\ No newline at end of file
--- /dev/null
+#include <stdlib.h>
+
+/* from stdlib.h */
+float strtof(const char *nptr, char **endptr)
+{
+ return (float)strtod(nptr, endptr);
+}
+
+double atof(const char *nptr)
+{
+ return strtod(nptr, NULL);
+}
+
+int abs(int __n)
+{
+ return (__n < 0) ? -__n : __n;
+}
+
+long labs(long __n)
+{
+ return (__n < 0L) ? -__n : __n;
+}
+
+long long llabs(long long __n)
+{
+ return (__n < 0LL) ? -__n : __n;
+}
+
+int rand(void)
+{
+ return (int)lrand48();
+}
+
+void srand(unsigned int __s)
+{
+ srand48(__s);
+}
+
+long random(void)
+{
+ return lrand48();
+}
+
+void srandom(unsigned int __s)
+{
+ srand48(__s);
+}
+
+/* from unistd.h */
+int getpagesize(void)
+{
+ extern unsigned int __page_size;
+ return __page_size;
+}
+
+int __getpageshift(void)
+{
+ extern unsigned int __page_shift;
+ return __page_shift;
+}
--- /dev/null
+##
+# This script is for fixing android platform compatibility problem
+##
+
+# To fix android NDK compatibility problem
+# Some functions, e.g. rand, srand. strtof ... are static inline prior to
+# android-L. So before android-L libc.so doesn't include them. If build
+# on android-L and run on an old platform(earlier than android-L), there will
+# be 'can't locate xxx' problem.
+import os
+
+Import('env')
+
+sif_env = env.Clone()
+
+sif_lib = sif_env.StaticLibrary(env.get('BUILD_DIR') + '/c_compat',
+ env.SrcToObj(os.path.abspath('./c_compat.c'), env.get('SRC_DIR')))
+
+env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+env.AppendUnique(LIBS = ['c_compat'])
\ No newline at end of file
--- /dev/null
+##
+# This script is for fixing android platform compatibility problem
+##
+import os
+
+Import('env')
+
+env.AppendUnique(CPPDEFINES = ['ANDROID_C11_COMPAT'])
+
+cc_env = env.Clone()
+cc_env.AppendUnique(CPPPATH = ['.'])
+cc_lib = cc_env.StaticLibrary(env.get('BUILD_DIR') + '/android_cpp11_compat',
+ env.SrcToObj(os.path.abspath('./android_cpp11_compat.cpp'), env.get('SRC_DIR')))
+
+env.AppendUnique(CPPPATH = [os.path.abspath('.')])
+env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+env.AppendUnique(LIBS = ['android_cpp11_compat'])
$(info SYSROOT=$(SYSROOT_LINK))
$(info LDFLAGS=$(TARGET_LDFLAGS) $(TARGET_NO_EXECUTE_LDFLAGS) $(TARGET_NO_UNDEFINED_LDFLAGS) $(TARGET_RELRO_LDFLAGS))
$(info TC_VER=$(TOOLCHAIN_VERSION))
+$(info PLATFORM=$(APP_PLATFORM))
\ No newline at end of file
if target_os == 'android':
examples_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
examples_env.AppendUnique(LIBS = ['gnustl_static'])
- examples_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
if not env.get('RELEASE'):
examples_env.AppendUnique(LIBS = ['log'])
if target_os == 'android':
ocicuc_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
- ocicuc_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
ocicuc_env.AppendUnique(LIBS = ['boost_program_options-gcc-mt-1_49', 'boost_thread-gcc-mt-1_49', 'gnustl_static'])
if not env.get('RELEASE'):
#include <OCException.h>
+#ifdef __ANDROID__
+#include "android_cpp11_compat.h"
+#endif
namespace cereal
{
target_os = env.get('TARGET_OS')
if target_os == 'android':
liboc_logger_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
- liboc_logger_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
liboc_logger_env.AppendUnique(LIBS = ['gnustl_static', 'log'])
if target_os not in ['arduino', 'windows', 'winrt']:
target_os = env.get('TARGET_OS')
if target_os == 'android':
examples_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
- examples_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
examples_env.AppendUnique(LIBS = ['gnustl_static'])
if target_os not in ['arduino', 'windows', 'winrt']:
examples_cpp = examples_env.Program('examples_cpp', 'test_logging.cpp')
Alias('liboc_logger_examples', [examples_c, examples_cpp])
-examples_env.AppendTarget('liboc_logger_examples')
\ No newline at end of file
+examples_env.AppendTarget('liboc_logger_examples')
if target_os == 'android':
oclib_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
- oclib_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
oclib_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
oclib_env.AppendUnique(LIBS = ['octbstack', 'coap', 'oc_logger', 'boost_thread-gcc-mt-1_49', 'gnustl_static', 'log'])
SConscript('soft-sensor-manager/SConscript')
# Build protocol plugin project
- SConscript('protocol-plugin/SConscript')
+ # protocol-plugin use 'inotify', this feature isn't support by MAC OSX
+ if target_os not in ['darwin', 'ios']:
+ SConscript('protocol-plugin/SConscript')
# Build notification manager project
# SConscript('notification-manager/SConscript')
if target_os == 'android':
notimgr_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
notimgr_env.AppendUnique(LIBS = ['gnustl_static'])
- notimgr_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
if not env.get('RELEASE'):
notimgr_env.AppendUnique(LIBS = ['log'])
if target_os == 'android':
plugins_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
plugins_env.AppendUnique(LIBS = ['gnustl_static'])
- plugins_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
plugins_env.AppendUnique(LIBS = [File(env.get('BUILD_DIR') + '/libmosquitto.a'),
'mosquitto', 'ssl', 'rt'])
if target_os == 'android':
things_manager_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
- things_manager_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
######################################################################
# Source files and Targets