From c26c0e6a978d50aa569a443707e84849cc907138 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 24 Jan 2013 17:54:56 +0000 Subject: [PATCH] Android support, part 1 --- dtool/Config.Android.pp | 378 +++++++++++++++++++++++++++ dtool/Config.FreeBSD.pp | 3 + dtool/Config.Irix.pp | 3 + dtool/Config.Linux.pp | 4 + dtool/Config.OSX.pp | 3 + dtool/Config.Win32.pp | 3 + dtool/Config.Win64.pp | 3 + dtool/Config.pp | 14 + dtool/LocalSetup.pp | 3 + dtool/pptempl/Global.pp | 2 + dtool/pptempl/PostConfig.pp | 53 ++++ dtool/src/dtoolbase/dtool_platform.h | 11 + dtool/src/dtoolutil/filename.cxx | 8 + dtool/src/prc/Sources.pp | 2 + dtool/src/prc/androidLogStream.cxx | 157 +++++++++++ dtool/src/prc/androidLogStream.h | 59 +++++ dtool/src/prc/notify.cxx | 8 + dtool/src/prc/notifyCategory.cxx | 17 ++ dtool/src/prc/p3prc_composite1.cxx | 2 +- dtool/src/prc/p3prc_composite2.cxx | 1 + 20 files changed, 733 insertions(+), 1 deletion(-) create mode 100644 dtool/Config.Android.pp create mode 100644 dtool/src/prc/androidLogStream.cxx create mode 100644 dtool/src/prc/androidLogStream.h diff --git a/dtool/Config.Android.pp b/dtool/Config.Android.pp new file mode 100644 index 0000000000..a8bc758d2e --- /dev/null +++ b/dtool/Config.Android.pp @@ -0,0 +1,378 @@ +// +// Config.Android.pp +// +// This file defines some custom config variables for the Android +// platform. It makes some initial guesses about compiler features, +// etc. +// + +// ******************************************************************* +// NOTE: you should not attempt to copy this file verbatim as your own +// personal Config.pp file. Instead, you should start with an empty +// Config.pp file, and add lines to it when you wish to override +// settings given in here. In the normal ppremake system, this file +// will always be read first, and then your personal Config.pp file +// will be read later, which gives you a chance to override the +// default settings found in this file. However, if you start by +// copying the entire file, it will be difficult to tell which +// settings you have customized, and it will be difficult to upgrade +// to a subsequent version of Panda. +// ******************************************************************* + +// Android is a Linux distribution. +#define IS_LINUX 1 + +// These libraries are provided by the Android NDK. +#define ZLIB_IPATH +#define ZLIB_LPATH +#define ZLIB_LIBS z +#define HAVE_ZLIB 1 + +#define GLES_IPATH +#define GLES_LPATH +#define GLES_LIBS GLESv1_CM +#define HAVE_GLES 1 + +#define GLES2_IPATH +#define GLES2_LPATH +#define GLES2_LIBS GLESv2 +#define HAVE_GLES2 1 + +#define EGL_IPATH +#define EGL_LPATH +#define EGL_LIBS EGL +#define HAVE_EGL 1 + +// We don't have these, of course, so let's disable +// them for convenience in case they were autodetected. +#define HAVE_DX8 +#define HAVE_DX9 +#define HAVE_CG + +// Compiler flags +#defer TOOLCHAIN_PATH $[ANDROID_NDK_HOME]/toolchains/$[ANDROID_TOOLCHAIN]/prebuilt/windows/bin +#defer TOOLCHAIN_PREFIX $[if $[eq $[ANDROID_ABI],x86],i686-linux-android,$[ANDROID_ABI]] +#defer CC $[TOOLCHAIN_PATH]/$[TOOLCHAIN_PREFIX]-gcc +#defer CXX $[TOOLCHAIN_PATH]/$[TOOLCHAIN_PREFIX]-g++ +#defer AR $[TOOLCHAIN_PATH]/$[TOOLCHAIN_PREFIX]-ar +#define C++FLAGS_GEN -fno-exceptions -fno-rtti + +#defer SYSROOT $[ANDROID_NDK_HOME]/platforms/$[ANDROID_PLATFORM]/arch-$[ANDROID_ARCH] +#defer SYSROOT_FLAGS --sysroot=$[subst \,/,$[osfilename $[SYSROOT]]] + +#defer EXTRA_IPATH $[ANDROID_NDK_HOME]/sources/android/native_app_glue $[SYSROOT]/usr/include +#defer EXTRA_LPATH $[SYSROOT]/usr/lib +#defer EXTRA_LIBS $[if $[eq $[BUILD_TYPE],android],,c m] + +// Define the CFLAGS and LDFLAGS settings for the various architectures. +#defer ANDROID_arm_CFLAGS\ + -fpic\ + -ffunction-sections\ + -funwind-tables\ + -fstack-protector\ + -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__\ + -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__\ + $[if $[eq $[ANDROID_ABI],armeabi-v7a],-march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16,-march=armv5te -mtune=xscale -msoft-float] + +#defer ANDROID_arm_LDFLAGS -march=armv7-a -Wl,--fix-cortex-a8 + +#define ANDROID_mips_CFLAGS\ + -fpic\ + -fno-strict-aliasing\ + -finline-functions\ + -ffunction-sections\ + -funwind-tables\ + -fmessage-length=0\ + -fno-inline-functions-called-once\ + -fgcse-after-reload\ + -frerun-cse-after-loop\ + -frename-registers + +#define ANDROID_mips_LDFLAGS + +#define ANDROID_x86_CFLAGS\ + -ffunction-sections\ + -funwind-tables\ + -fstack-protector + +#define ANDROID_x86_LDFLAGS + +// Select the flags for our architecture and add some common ones. +#defer ANDROID_CFLAGS $[ANDROID_$[ANDROID_ARCH]_CFLAGS] -DANDROID -Wa,$[if $[ANDROID_DISABLE_NX],--execstack,--noexecstack] +#defer ANDROID_LDFLAGS -Wl,--no-undefined\ + -Wl,-z,$[if $[ANDROID_DISABLE_NX],execstack,noexecstack]\ + -Wl,-z,$[if $[ANDROID_DISABLE_RELRO],norelro,relro]\ + -Wl,-z,$[if $[ANDROID_DISABLE_RELRO],lazy,now] + +// How to compile a C or C++ file into a .o file. $[target] is the +// name of the .o file, $[source] is the name of the source file, +// $[ipath] is a space-separated list of directories to search for +// include files, and $[flags] is a list of additional flags to pass +// to the compiler. +#defer os_ipath $[subst \,/,$[osfilename $[ipath]]] +#defer COMPILE_C $[CC] $[SYSROOT_FLAGS] $[ANDROID_CFLAGS] $[CFLAGS_GEN] $[flags] $[os_ipath:%=-I%] -c $[source] -o $[target] +#defer COMPILE_C++ $[CXX] $[SYSROOT_FLAGS] $[ANDROID_CFLAGS] $[C++FLAGS_GEN] $[flags] $[os_ipath:%=-I%] -c $[source] -o $[target] + +// What flags should be passed to both C and C++ compilers to enable +// debug symbols? This will be supplied when OPTIMIZE (above) is set +// to 1, 2, or 3. +#defer DEBUGFLAGS -g + +// What flags should be passed to both C and C++ compilers to enable +// compiler optimizations? This will be supplied when OPTIMIZE +// (above) is set to 2, 3, or 4. +#defer OPTFLAGS -O2 + +// By convention, any source file that contains the string _no_opt_ in +// its filename won't have the above compiler optimizations run for it. +#defer no_opt $[findstring _no_opt_,$[source]] + +// What define variables should be passed to the compilers for each +// value of OPTIMIZE? We separate this so we can pass these same +// options to interrogate, guaranteeing that the correct interfaces +// are generated. Do not include -D here; that will be supplied +// automatically. +#defer CDEFINES_OPT1 $[EXTRA_CDEFS] +#defer CDEFINES_OPT2 $[EXTRA_CDEFS] +#defer CDEFINES_OPT3 $[EXTRA_CDEFS] +#defer CDEFINES_OPT4 $[EXTRA_CDEFS] + +// What additional flags should be passed for each value of OPTIMIZE +// (above)? We separate out the compiler-optimization flags, above, +// so we can compile certain files that give optimizers trouble (like +// the output of lex and yacc) without them, but with all the other +// relevant flags. + +#define ANDROID_DEBUG_CFLAGS -fno-omit-frame-pointer -fno-strict-aliasing +#define ANDROID_RELEASE_CFLAGS -fomit-frame-pointer -fstrict-aliasing -funswitch-loops -finline-limit=300 + +#defer CFLAGS_OPT1 $[CDEFINES_OPT1:%=-D%] -Wall $[DEBUGFLAGS] $[ANDROID_DEBUG_FLAGS] +#defer CFLAGS_OPT2 $[CDEFINES_OPT2:%=-D%] -Wall $[DEBUGFLAGS] $[if $[no_opt],,$[OPTFLAGS]] $[ANDROID_DEBUG_FLAGS] +#defer CFLAGS_OPT3 $[CDEFINES_OPT3:%=-D%] $[DEBUGFLAGS] $[if $[no_opt],,$[OPTFLAGS]] $[ANDROID_RELEASE_FLAGS] +#defer CFLAGS_OPT4 $[CDEFINES_OPT4:%=-D%] $[if $[no_opt],,$[OPTFLAGS]] $[ANDROID_RELEASE_FLAGS] + +// What additional flags should be passed to both compilers when +// building shared (relocatable) sources? Some architectures require +// special support for this. +#defer CFLAGS_SHARED -fPIC + +// How to generate a C or C++ executable from a collection of .o +// files. $[target] is the name of the binary to generate, and +// $[sources] is the list of .o files. $[libs] is a space-separated +// list of dependent libraries, and $[lpath] is a space-separated list +// of directories in which those libraries can be found. +#defer os_lpath $[subst \,/,$[osfilename $[lpath]]] +#defer LINK_BIN_C $[LINK_BIN_C++] +#defer LINK_BIN_C++ $[cxx_ld]\ + -Wl,--gc-sections\ + -Wl,-z,nocopyreloc\ + $[SYSROOT_FLAGS]\ + $[sources]\ + $[flags]\ + $[os_lpath:%=-L%] $[libs:%=-l%]\ + -o $[target] + +// How to generate a static C or C++ library. $[target] is the +// name of the library to generate, and $[sources] is the list of .o +// files that will go into the library. +#defer STATIC_LIB_C $[AR] cru $[target] $[sources] +#defer STATIC_LIB_C++ $[AR] cru $[target] $[sources] + +// How to run ranlib, if necessary, after generating a static library. +// $[target] is the name of the library. Set this to the empty string +// if ranlib is not necessary on your platform. +#defer RANLIB ranlib $[target] + +// Where to put the so_locations file, used by an Irix MIPSPro +// compiler, to generate a map of shared library memory locations. +#defer SO_LOCATIONS $[DTOOL_INSTALL]/etc/so_locations + + +// How to generate a shared C or C++ library. $[source] and $[target] +// as above, and $[libs] is a space-separated list of dependent +// libraries, and $[lpath] is a space-separated list of directories in +// which those libraries can be found. +#defer SHARED_LIB_C $[SHARED_LIB_C++] +#defer SHARED_LIB_C++ $[cxx_ld]\ + -Wl,-soname,$[notdir $[target]]\ + -shared\ + $[SYSROOT_FLAGS]\ + $[sources]\ + $[flags]\ + $[os_lpath:%=-L%] $[libs:%=-l%]\ + -o $[target] +#define BUNDLE_LIB_C++ + +// How to install a data file or executable file. $[local] is the +// local name of the file to install, and $[dest] is the name of the +// directory to put it in. + +// On Unix systems, we strongly prefer using the install program to +// install files. This has nice features like automatically setting +// the permissions bits, and also is usually clever enough to install +// a running program without crashing the running instance. However, +// it doesn't understanding installing a program from a subdirectory, +// so we have to cd into the source directory first. +#defer install_dash_p $[if $[KEEP_TIMESTAMPS],-p,] +#defer INSTALL $[if $[ne $[dir $[local]], ./],cd ./$[dir $[local]] &&] install -m $[INSTALL_UMASK_DATA] $[install_dash_p] $[notdir $[local]] $[dest]/ +#defer INSTALL_PROG $[if $[ne $[dir $[local]], ./],cd ./$[dir $[local]] &&] install -m $[INSTALL_UMASK_PROG] $[install_dash_p] $[notdir $[local]] $[dest]/ + +#define SYSTEM_IGATE_FLAGS -D__const=const -Dvolatile -Dmutable + +// Posix thread support is provided by the Android NDK. +#define HAVE_POSIX_THREADS 1 +#define THREADS_LIBS + +// Is the platform big-endian (like an SGI workstation) or +// little-endian (like a PC)? Define this to the empty string to +// indicate little-endian, or nonempty to indicate big-endian. +#define WORDS_BIGENDIAN + +// Does the C++ compiler support namespaces? +#define HAVE_NAMESPACE 1 + +// Does the C++ compiler support ios::binary? +#define HAVE_IOS_BINARY 1 + +// How about the typename keyword? +#define HAVE_TYPENAME 1 + +// Will the compiler avoid inserting extra bytes in structs between a +// base struct and its derived structs? It is safe to define this +// false if you don't know, but if you know that you can get away with +// this you may gain a tiny performance gain by defining this true. +// If you define this true incorrectly, you will get lots of +// assertion failures on execution. +#define SIMPLE_STRUCT_POINTERS + +// Do we have a gettimeofday() function? +#define HAVE_GETTIMEOFDAY 1 + +// Does gettimeofday() take only one parameter? +#define GETTIMEOFDAY_ONE_PARAM + +// Do we have getopt() and/or getopt_long_only() built into the +// system? +#define HAVE_GETOPT 1 +#define HAVE_GETOPT_LONG_ONLY 1 + +// Are the above getopt() functions defined in getopt.h, or somewhere else? +#define PHAVE_GETOPT_H 1 + +// Can we determine the terminal width by making an ioctl(TIOCGWINSZ) call? +#define IOCTL_TERMINAL_WIDTH 1 + +// Do the system headers define a "streamsize" typedef? How about the +// ios::binary enumerated value? And other ios typedef symbols like +// ios::openmode and ios::fmtflags? +#define HAVE_STREAMSIZE 1 +#define HAVE_IOS_BINARY 1 +#define HAVE_IOS_TYPEDEFS 1 + +// Can we safely call getenv() at static init time? +#define STATIC_INIT_GETENV 1 + +// Can we read the files /proc/self/* to determine our +// environment variables at static init time? +#define HAVE_PROC_SELF_EXE 1 +#define HAVE_PROC_SELF_MAPS 1 +#define HAVE_PROC_SELF_ENVIRON 1 +#define HAVE_PROC_SELF_CMDLINE 1 + +// Do we have a global pair of argc/argv variables that we can read at +// static init time? Should we prototype them? What are they called? +#define HAVE_GLOBAL_ARGV +#define PROTOTYPE_GLOBAL_ARGV +#define GLOBAL_ARGV +#define GLOBAL_ARGC + +// Should we include or ? Define PHAVE_IOSTREAM +// to nonempty if we should use , or empty if we should use +// . +#define PHAVE_IOSTREAM 1 + +// Do we have a true stringstream class defined in ? +#define PHAVE_SSTREAM 1 + +// Does fstream::open() require a third parameter, specifying the +// umask? Versions of gcc prior to 3.2 had this. +#define HAVE_OPEN_MASK + +// Do we have the lockf() function available? +#define HAVE_LOCKF + +// Do the compiler or system libraries define wchar_t for you? +#define HAVE_WCHAR_T 1 + +// Does define the typedef wstring? Most do, but for some +// reason, versions of gcc before 3.0 didn't do this. +#define HAVE_WSTRING 1 + +// Do we have ? +#define PHAVE_NEW 1 + +// Do we have ? +#define PHAVE_IO_H + +// Do we have ? +#define PHAVE_MALLOC_H 1 + +// Do we have ? +#define PHAVE_ALLOCA_H 1 + +// Do we have ? +#define PHAVE_LOCALE_H 1 + +// Do we have ? +#define PHAVE_STRING_H 1 + +// Do we have ? +#define PHAVE_STDLIB_H 1 + +// Do we have ? +#define PHAVE_LIMITS_H 1 + +// Do we have ? +#define PHAVE_MINMAX_H + +// Do we have ? +#define PHAVE_SYS_TYPES_H 1 +#define PHAVE_SYS_TIME_H 1 + +// Do we have ? +#define PHAVE_UNISTD_H 1 + +// Do we have ? +#define PHAVE_UTIME_H 1 + +// Do we have ? +#define PHAVE_DIRENT_H 1 + +// Do we have (and do we want to use it instead of dirent.h)? +#define PHAVE_GLOB_H + +// Do we have (and presumably a Linux-style audio +// interface)? +#define PHAVE_SYS_SOUNDCARD_H 1 + +// Do we have (and therefore makecontext() / swapcontext())? +#define PHAVE_UCONTEXT_H 1 + +// Do we have ? This enables us to use raw mouse input. +#define PHAVE_LINUX_INPUT_H 1 + +// Do we have RTTI (and )? +// Technically, Android has RTTI support now, +// but we keep it disabled for performance reasons. +#define HAVE_RTTI + +// Do we have ? +#define PHAVE_STDINT_H 1 + +// We need 64-bit file i/o +#define __USE_LARGEFILE64 1 + +// The dynamic library file extension (usually .so .dll or .dylib): +#define DYNAMIC_LIB_EXT .so +#define STATIC_LIB_EXT .a +#define BUNDLE_EXT diff --git a/dtool/Config.FreeBSD.pp b/dtool/Config.FreeBSD.pp index 9db29333c8..61e8e7fcd0 100644 --- a/dtool/Config.FreeBSD.pp +++ b/dtool/Config.FreeBSD.pp @@ -220,6 +220,9 @@ // umask? Versions of gcc prior to 3.2 had this. #define HAVE_OPEN_MASK +// Do we have the lockf() function available? +#define HAVE_LOCKF 1 + // Do the compiler or system libraries define wchar_t for you? #define HAVE_WCHAR_T 1 diff --git a/dtool/Config.Irix.pp b/dtool/Config.Irix.pp index 6522228c2d..7939568c7f 100644 --- a/dtool/Config.Irix.pp +++ b/dtool/Config.Irix.pp @@ -95,6 +95,9 @@ // umask? #define HAVE_OPEN_MASK 1 +// Do we have the lockf() function available? +#define HAVE_LOCKF 1 + // Do the compiler or system libraries define wchar_t for you? #define HAVE_WCHAR_T 1 diff --git a/dtool/Config.Linux.pp b/dtool/Config.Linux.pp index 35a8b99c79..96ecc27a73 100644 --- a/dtool/Config.Linux.pp +++ b/dtool/Config.Linux.pp @@ -263,6 +263,9 @@ // umask? Versions of gcc prior to 3.2 had this. #define HAVE_OPEN_MASK +// Do we have the lockf() function available? +#define HAVE_LOCKF 1 + // Do the compiler or system libraries define wchar_t for you? #define HAVE_WCHAR_T 1 @@ -273,6 +276,7 @@ // Do we have ? #define PHAVE_NEW 1 + // Do we have ? #define PHAVE_IO_H diff --git a/dtool/Config.OSX.pp b/dtool/Config.OSX.pp index bd224f40fe..24c422cc2d 100644 --- a/dtool/Config.OSX.pp +++ b/dtool/Config.OSX.pp @@ -222,6 +222,9 @@ // umask? Versions of gcc prior to 3.2 had this. #define HAVE_OPEN_MASK +// Do we have the lockf() function available? +#define HAVE_LOCKF 1 + // Do the compiler or system libraries define wchar_t for you? #define HAVE_WCHAR_T 1 diff --git a/dtool/Config.Win32.pp b/dtool/Config.Win32.pp index a1394360c4..84ad72749c 100644 --- a/dtool/Config.Win32.pp +++ b/dtool/Config.Win32.pp @@ -100,6 +100,9 @@ // umask? #define HAVE_OPEN_MASK +// Do we have the lockf() function available? +#define HAVE_LOCKF 1 + // Do the compiler or system libraries define wchar_t for you? #define HAVE_WCHAR_T 1 diff --git a/dtool/Config.Win64.pp b/dtool/Config.Win64.pp index 72e43f74ef..a1af6e7fd5 100755 --- a/dtool/Config.Win64.pp +++ b/dtool/Config.Win64.pp @@ -100,6 +100,9 @@ // umask? #define HAVE_OPEN_MASK +// Do we have the lockf() function available? +#define HAVE_LOCKF 1 + // Do the compiler or system libraries define wchar_t for you? #define HAVE_WCHAR_T 1 diff --git a/dtool/Config.pp b/dtool/Config.pp index 85bd5cad39..2addd06fb4 100644 --- a/dtool/Config.pp +++ b/dtool/Config.pp @@ -402,6 +402,20 @@ // Don't enable this unless you know what you're doing! #define BUILD_IPHONE +// Panda contains some experimental code to compile for Android. This +// requires the Google Android NDK. +// Besides BUILD_ANDROID, you'll also have to set ANDROID_NDK_HOME +// to the location of the Android NDK directory. ANDROID_NDK_HOME may +// not contain any spaces. +// Furthermore, ANDROID_ABI can be set to armeabi, armeabi-v7a, x86, +// or mips, depending on which architecture should be targeted. +#define ANDROID_NDK_HOME +#define ANDROID_ABI armeabi +#define ANDROID_STL gnustl_shared +#define ANDROID_PLATFORM android-9 +#define ANDROID_ARCH arm +#defer ANDROID_TOOLCHAIN $[if $[eq $[ANDROID_ARCH],arm],arm-linux-androideabi] + // Do you want to use one of the alternative malloc implementations? // This is almost always a good idea on Windows, where the standard // malloc implementation appears to be pretty poor, but probably diff --git a/dtool/LocalSetup.pp b/dtool/LocalSetup.pp index 429e8eec73..219f324624 100644 --- a/dtool/LocalSetup.pp +++ b/dtool/LocalSetup.pp @@ -578,6 +578,9 @@ $[cdefine HAVE_NAMESPACE] /* Define if fstream::open() accepts a third parameter for umask. */ $[cdefine HAVE_OPEN_MASK] +/* Define if we have a lockf() function. */ +$[cdefine HAVE_LOCKF] + /* Define if some header file defines wchar_t. */ $[cdefine HAVE_WCHAR_T] diff --git a/dtool/pptempl/Global.pp b/dtool/pptempl/Global.pp index cd5f385f0e..119b021eb3 100644 --- a/dtool/pptempl/Global.pp +++ b/dtool/pptempl/Global.pp @@ -790,6 +790,8 @@ #set alt_libs $[alt_libs] $[WIN_SYS_LIBS] $[components $[WIN_SYS_LIBS],$[active_libs] $[transitive_link]] #elif $[OSX_PLATFORM] #set alt_libs $[alt_libs] $[OSX_SYS_LIBS] $[components $[OSX_SYS_LIBS],$[active_libs] $[transitive_link]] + #elif $[eq $[PLATFORM], Android] + #set alt_libs $[alt_libs] $[ANDROID_SYS_LIBS] $[components $[ANDROID_SYS_LIBS],$[active_libs] $[transitive_link]] #else #set alt_libs $[alt_libs] $[UNIX_SYS_LIBS] $[components $[UNIX_SYS_LIBS],$[active_libs] $[transitive_link]] #endif diff --git a/dtool/pptempl/PostConfig.pp b/dtool/pptempl/PostConfig.pp index e8f0a8f5c6..c2244f2b00 100644 --- a/dtool/pptempl/PostConfig.pp +++ b/dtool/pptempl/PostConfig.pp @@ -28,5 +28,58 @@ #define OSX_CFLAGS -isysroot $[dev]/SDKs/$[IPH_PLATFORM]$[IPH_VERSION].sdk $[osflags] #defer ODIR_SUFFIX -$[IPH_PLATFORM] +#endif + +#if $[eq $[PLATFORM], Android] + +// These are the flags also used by Android's own ndk-build. +#if $[eq $[ANDROID_ARCH],arm] +#define target_cflags\ + -fpic\ + -ffunction-sections\ + -funwind-tables\ + -fstack-protector\ + -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__\ + -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ + +#elif $[eq $[ANDROID_ARCH],mips] +#define target_cflags\ + -fpic\ + -fno-strict-aliasing\ + -finline-functions\ + -ffunction-sections\ + -funwind-tables\ + -fmessage-length=0\ + -fno-inline-functions-called-once\ + -fgcse-after-reload\ + -frerun-cse-after-loop\ + -frename-registers + +#elif $[eq $[ANDROID_ABI],x86] +#define target_cflags\ + -ffunction-sections\ + -funwind-tables\ + -fstack-protector +#endif + +#if $[eq $[ANDROID_ABI],armeabi-v7a] +#define target_cflags $[target_cflags]\ + -march=armv7-a \ + -mfloat-abi=softfp \ + -mfpu=vfpv3-d16 + +#define target_ldflags $[target_ldflags]\ + -march=armv7-a \ + -Wl,--fix-cortex-a8 + +#elif $[eq $[ANDROID_ABI],armeabi] +#define target_cflags $[target_cflags]\ + -march=armv5te \ + -mtune=xscale \ + -msoft-float +#endif + +#define ANDROID_CFLAGS $[target_cflags] $[ANDROID_CFLAGS] +#define ANDROID_LDFLAGS $[target_ldflags] $[ANDROID_LDFLAGS] #endif diff --git a/dtool/src/dtoolbase/dtool_platform.h b/dtool/src/dtoolbase/dtool_platform.h index b0bcf47602..ccdb48539e 100755 --- a/dtool/src/dtoolbase/dtool_platform.h +++ b/dtool/src/dtoolbase/dtool_platform.h @@ -49,6 +49,17 @@ #define DTOOL_PLATFORM "freebsd_i386" #endif +#elif defined(__ANDROID__) +#if defined(__ARM_ARCH_7A__) +#define DTOOL_PLATFORM "android_armv7a" +#elif defined(__arm__) +#define DTOOL_PLATFORM "android_arm" +#elif defined(__mips__) +#define DTOOL_PLATFORM "android_mips" +#elif defined(__i386__) +#define DTOOL_PLATFORM "android_i386" +#endif + #elif defined(__x86_64) #define DTOOL_PLATFORM "linux_amd64" diff --git a/dtool/src/dtoolutil/filename.cxx b/dtool/src/dtoolutil/filename.cxx index 5517ec56fc..260b4740fd 100644 --- a/dtool/src/dtoolutil/filename.cxx +++ b/dtool/src/dtoolutil/filename.cxx @@ -3010,7 +3010,11 @@ atomic_compare_and_exchange_contents(string &orig_contents, orig_contents = string(); +#ifdef HAVE_LOCKF if (lockf(fd, F_LOCK, 0) != 0) { +#else + if (flock(fd, LOCK_EX) != 0) { +#endif perror(os_specific.c_str()); close(fd); return false; @@ -3127,7 +3131,11 @@ atomic_read_contents(string &contents) const { contents = string(); +#ifdef HAVE_LOCKF if (lockf(fd, F_LOCK, 0) != 0) { +#else + if (flock(fd, LOCK_EX) != 0) { +#endif perror(os_specific.c_str()); close(fd); return false; diff --git a/dtool/src/prc/Sources.pp b/dtool/src/prc/Sources.pp index 1ecf9b1ac3..a5bc96963b 100644 --- a/dtool/src/prc/Sources.pp +++ b/dtool/src/prc/Sources.pp @@ -4,6 +4,8 @@ #begin lib_target #define TARGET p3prc + #define ANDROID_SYS_LIBS log + #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx #define SOURCES \ diff --git a/dtool/src/prc/androidLogStream.cxx b/dtool/src/prc/androidLogStream.cxx new file mode 100644 index 0000000000..7f4cb943fb --- /dev/null +++ b/dtool/src/prc/androidLogStream.cxx @@ -0,0 +1,157 @@ +// Filename: androidLogStream.cxx +// Created by: rdb (12Jan13) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#include "androidLogStream.h" +#include "configVariableString.h" + +#ifdef ANDROID + +#include + +//////////////////////////////////////////////////////////////////// +// Function: AndroidLogStreamBuf::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +AndroidLogStream::AndroidLogStreamBuf:: +AndroidLogStreamBuf(int priority) : + _priority(priority) { + + static ConfigVariableString android_log_tag + ("android-log-tag", "Panda3D", + PRC_DESC("This defines the tag that Panda3D will use when writing to the " + "Android log. The default is \"Panda3D\".")); + + if (_tag.empty()) { + _tag = android_log_tag.get_value(); + } + + // The AndroidLogStreamBuf doesn't actually need a buffer--it's happy + // writing characters one at a time, since they're just getting + // stuffed into a string. (Although the code is written portably + // enough to use a buffer correctly, if we had one.) + setg(0, 0, 0); + setp(0, 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: AndroidLogStreamBuf::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +AndroidLogStream::AndroidLogStreamBuf:: +~AndroidLogStreamBuf() { + sync(); +} + +//////////////////////////////////////////////////////////////////// +// Function: AndroidLogStreamBuf::sync +// Access: Public, Virtual +// Description: Called by the system ostream implementation when the +// buffer should be flushed to output (for instance, on +// destruction). +//////////////////////////////////////////////////////////////////// +int AndroidLogStream::AndroidLogStreamBuf:: +sync() { + streamsize n = pptr() - pbase(); + + // Write the characters that remain in the buffer. + for (char *p = pbase(); p < pptr(); ++p) { + write_char(*p); + } + + pbump(-n); // Reset pptr(). + return 0; // EOF to indicate write full. +} + +//////////////////////////////////////////////////////////////////// +// Function: AndroidLogStreamBuf::overflow +// Access: Public, Virtual +// Description: Called by the system ostream implementation when its +// internal buffer is filled, plus one character. +//////////////////////////////////////////////////////////////////// +int AndroidLogStream::AndroidLogStreamBuf:: +overflow(int ch) { + streamsize n = pptr() - pbase(); + + if (n != 0 && sync() != 0) { + return EOF; + } + + if (ch != EOF) { + // Write one more character. + write_char(ch); + } + + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: AndroidLogStreamBuf::write_char +// Access: Private +// Description: Stores a single character. +//////////////////////////////////////////////////////////////////// +void AndroidLogStream::AndroidLogStreamBuf:: +write_char(char c) { + if (c == '\n') { + // Write a line to the log file. + __android_log_write(_priority, _tag.c_str(), _data.c_str()); + _data.clear(); + } else { + _data += c; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: AndroidLogStream::Constructor +// Access: Private +// Description: +//////////////////////////////////////////////////////////////////// +AndroidLogStream:: +AndroidLogStream(int priority) : + ostream(new AndroidLogStreamBuf(priority)) { +} + +//////////////////////////////////////////////////////////////////// +// Function: AndroidLogStream::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +AndroidLogStream:: +~AndroidLogStream() { + delete rdbuf(); +} + +//////////////////////////////////////////////////////////////////// +// Function: AndroidLogStream::out +// Access: Public, Static +// Description: Returns an AndroidLogStream suitable for writing +// log messages with the indicated severity. +//////////////////////////////////////////////////////////////////// +ostream &AndroidLogStream:: +out(NotifySeverity severity) { + static AndroidLogStream* streams[NS_fatal + 1] = {NULL}; + + if (streams[severity] == NULL) { + int priority = ANDROID_LOG_UNKNOWN; + if (severity != NS_unspecified) { + priority = ((int)severity) + 1; + } + streams[severity] = new AndroidLogStream(priority); + } + + return *streams[severity]; +} + +#endif // ANDROID diff --git a/dtool/src/prc/androidLogStream.h b/dtool/src/prc/androidLogStream.h new file mode 100644 index 0000000000..dbe7f1f25b --- /dev/null +++ b/dtool/src/prc/androidLogStream.h @@ -0,0 +1,59 @@ +// Filename: androidLogStream.h +// Created by: rdb (12Jan13) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#ifndef ANDROIDLOGSTREAM_H +#define ANDROIDLOGSTREAM_H + +#ifdef ANDROID + +#include "dtoolbase.h" +#include "notifySeverity.h" + +#include +#include + +//////////////////////////////////////////////////////////////////// +// Class : AndroidLogStream +// Description : This is a type of ostream that writes each line +// to the Android log. +/////////////////////////////////////////////////////////////////// +class AndroidLogStream : public ostream { +private: + class AndroidLogStreamBuf : public streambuf { + public: + AndroidLogStreamBuf(int priority); + virtual ~AndroidLogStreamBuf(); + + protected: + virtual int overflow(int c); + virtual int sync(); + + private: + void write_char(char c); + + int _priority; + string _tag; + string _data; + }; + + AndroidLogStream(int priority); + +public: + virtual ~AndroidLogStream(); + static ostream &out(NotifySeverity severity); +}; + +#endif // ANDROID + +#endif diff --git a/dtool/src/prc/notify.cxx b/dtool/src/prc/notify.cxx index 713c90a7f7..b8fe219e9b 100644 --- a/dtool/src/prc/notify.cxx +++ b/dtool/src/prc/notify.cxx @@ -26,6 +26,10 @@ #include #endif +#ifdef ANDROID +#include +#endif + Notify *Notify::_global_ptr = (Notify *)NULL; //////////////////////////////////////////////////////////////////// @@ -439,7 +443,11 @@ assert_failure(const char *expression, int line, return (*_assert_handler)(expression, line, source_file); } +#ifdef ANDROID + __android_log_assert("assert", "Panda3D", "Assertion failed: %s", message.c_str()); +#else nout << "Assertion failed: " << message << "\n"; +#endif // This is redefined here, shadowing the defining in config_prc.h, // so we can guarantee it has already been constructed. diff --git a/dtool/src/prc/notifyCategory.cxx b/dtool/src/prc/notifyCategory.cxx index 64f084e70c..6998af4270 100644 --- a/dtool/src/prc/notifyCategory.cxx +++ b/dtool/src/prc/notifyCategory.cxx @@ -19,6 +19,10 @@ #include "configVariableBool.h" #include "config_prc.h" +#ifdef ANDROID +#include "androidLogStream.h" +#endif + #include // for strftime(). #include @@ -61,6 +65,18 @@ NotifyCategory(const string &fullname, const string &basename, ostream &NotifyCategory:: out(NotifySeverity severity, bool prefix) const { if (is_on(severity)) { + +#ifdef ANDROID + // Android redirects stdio and stderr to /dev/null, + // but does provide its own logging system. We use a special + // type of stream that redirects it to Android's log system. + if (prefix) { + return AndroidLogStream::out(severity) << *this << ": "; + } else { + return AndroidLogStream::out(severity); + } +#else + if (prefix) { if (get_notify_timestamp()) { // Format a timestamp to include as a prefix as well. @@ -80,6 +96,7 @@ out(NotifySeverity severity, bool prefix) const { } else { return nout; } +#endif } else if (severity <= NS_debug && get_check_debug_notify_protect()) { // Someone issued a debug Notify output statement without diff --git a/dtool/src/prc/p3prc_composite1.cxx b/dtool/src/prc/p3prc_composite1.cxx index 2510bce8fb..bc58a6d44b 100644 --- a/dtool/src/prc/p3prc_composite1.cxx +++ b/dtool/src/prc/p3prc_composite1.cxx @@ -1,3 +1,4 @@ +#include "androidLogStream.cxx" #include "config_prc.cxx" #include "configDeclaration.cxx" #include "configFlags.cxx" @@ -12,4 +13,3 @@ #include "configVariableFilename.cxx" #include "configVariableInt.cxx" #include "configVariableInt64.cxx" -#include "configVariableList.cxx" diff --git a/dtool/src/prc/p3prc_composite2.cxx b/dtool/src/prc/p3prc_composite2.cxx index 0b4c5a8f7b..0791ee0b01 100644 --- a/dtool/src/prc/p3prc_composite2.cxx +++ b/dtool/src/prc/p3prc_composite2.cxx @@ -1,3 +1,4 @@ +#include "configVariableList.cxx" #include "configVariableManager.cxx" #include "configVariableSearchPath.cxx" #include "configVariableString.cxx"