Add APP_STL to select the C++ STL automatically.

This patch allows developers to define APP_STL in their
Application.mk in order to select the C++ STL they want to
use automatically.

Valid values are "system", "stlport_static" and "stlport_shared".
See the new document docs/STL-SUPPORT.html for more details.

Note that the patch also contains changes that will make room
for other C++ STL implementations (GNU libstdc++ and maybe uSTL)

Change-Id: Ica3fbad90d31deb9699e6cfb4a1cff3cd2e6c890
diff --git a/build/core/add-application.mk b/build/core/add-application.mk
index 5c6870c..70c133e 100644
--- a/build/core/add-application.mk
+++ b/build/core/add-application.mk
@@ -193,6 +193,17 @@
   APP_CFLAGS := -O2 -DNDEBUG -g $(APP_CFLAGS)
 endif
 
+# Check that APP_STL is defined. If not, use the default value (system)
+# otherwise, check that the name is correct.
+APP_STL := $(strip $(APP_STL))
+ifndef APP_STL
+    APP_STL := system
+else
+    $(call ndk-stl-check,$(APP_STL))
+endif
+
+
+
 $(if $(call get,$(_map),defined),\
   $(call __ndk_info,Weird, the application $(_app) is already defined by $(call get,$(_map),defined))\
   $(call __ndk_error,Aborting)\
diff --git a/build/core/definitions.mk b/build/core/definitions.mk
index b2b3e0d..0b3893b 100644
--- a/build/core/definitions.mk
+++ b/build/core/definitions.mk
@@ -853,7 +853,7 @@
 # the list of variables that *may* be defined in Application.mk files
 NDK_APP_VARS_OPTIONAL := APP_OPTIM APP_CPPFLAGS APP_CFLAGS APP_CXXFLAGS \
                          APP_PLATFORM APP_BUILD_SCRIPT APP_ABI APP_MODULES \
-                         APP_PROJECT_PATH
+                         APP_PROJECT_PATH APP_STL
 
 # the list of all variables that may appear in an Application.mk file
 # or defined by the build scripts.
@@ -1254,3 +1254,76 @@
 $(call module-class-register,PREBUILT_STATIC_LIBRARY,,)
 $(call module-class-set-prebuilt,PREBUILT_STATIC_LIBRARY)
 
+#
+# C++ STL support
+#
+
+# The list of registered STL implementations we support
+NDK_STL_LIST :=
+
+# Used internally to register a given STL implementation, see below.
+#
+# $1: STL name as it appears in APP_STL (e.g. system)
+# $2: STL module name (e.g. cxx-stl/system)
+# $3: list of static libraries all modules will depend on
+# $4: list of shared libraries all modules will depend on
+#
+ndk-stl-register = \
+    $(eval __ndk_stl := $(strip $1)) \
+    $(eval NDK_STL_LIST += $(__ndk_stl)) \
+    $(eval NDK_STL.$(__ndk_stl).IMPORT_MODULE := $(strip $2)) \
+    $(eval NDK_STL.$(__ndk_stl).STATIC_LIBS := $(strip $3)) \
+    $(eval NDK_STL.$(__ndk_stl).SHARED_LIBS := $(strip $4))
+
+# Called to check that the value of APP_STL is a valid one.
+# $1: STL name as it apperas in APP_STL (e.g. 'system')
+#
+ndk-stl-check = \
+    $(if $(call set_is_member,$(NDK_STL_LIST),$1),,\
+        $(call __ndk_info,Invalid APP_STL value: $1)\
+        $(call __ndk_info,Please use one of the following instead: $(NDK_STL_LIST))\
+        $(call __ndk_error,Aborting))
+
+# Called before the top-level Android.mk is parsed to
+# select the STL implementation.
+# $1: STL name as it appears in APP_STL (e.g. system)
+#
+ndk-stl-select = \
+    $(call import-module,$(NDK_STL.$1.IMPORT_MODULE))
+
+# Called after all Android.mk files are parsed to add
+# proper STL dependencies to every C++ module.
+# $1: STL name as it appears in APP_STL (e.g. system)
+#
+ndk-stl-add-dependencies = \
+    $(call modules-add-c++-dependencies,\
+        $(NDK_STL.$1.STATIC_LIBS),\
+        $(NDK_STL.$1.SHARED_LIBS))
+
+#
+#
+
+# Register the 'system' STL implementation
+#
+$(call ndk-stl-register,\
+    system,\
+    cxx-stl/system,\
+    libstdc++,\
+    )
+
+# Register the 'stlport_static' STL implementation
+#
+$(call ndk-stl-register,\
+    stlport_static,\
+    android/stlport,\
+    stlport_static,\
+    )
+
+# Register the 'stlport_shared' STL implementation
+#
+$(call ndk-stl-register,\
+    stlport_shared,\
+    android/stlport,\
+    ,\
+    stlport_shared\
+    )
diff --git a/build/core/setup-toolchain.mk b/build/core/setup-toolchain.mk
index 1a120f0..301aab2 100644
--- a/build/core/setup-toolchain.mk
+++ b/build/core/setup-toolchain.mk
@@ -18,7 +18,7 @@
 #
 
 $(call assert-defined,TARGET_PLATFORM TARGET_ARCH TARGET_ARCH_ABI)
-$(call assert-defined,NDK_APPS)
+$(call assert-defined,NDK_APPS NDK_APP_STL)
 
 # Check that we have a toolchain that supports the current ABI.
 # NOTE: If NDK_TOOLCHAIN is defined, we're going to use it.
@@ -138,16 +138,13 @@
 # free the dictionary of LOCAL_MODULE definitions
 $(call modules-clear)
 
+$(call ndk-stl-select,$(NDK_APP_STL))
+
 # now parse the Android.mk for the application, this records all
 # module declarations, but does not populate the dependency graph yet.
 include $(NDK_APP_BUILD_SCRIPT)
 
-# special case of C++ runtime support: If any module has C++ sources,
-# we need to parse the Android.mk for our selected C++ runtime and
-# add it as an automatic dependency to the corresponding modules.
-#
-include $(NDK_ROOT)/sources/cxx-stl/system/setup.mk
-$(call modules-add-c++-dependencies,$(NDK_APP_CXX_STATIC_LIBRARIES),$(NDK_APP_CXX_SHARED_LIBRARIES))
+$(call ndk-stl-add-dependencies,$(NDK_APP_STL))
 
 # recompute all dependencies between modules
 $(call modules-compute-dependencies)
diff --git a/docs/APPLICATION-MK.html b/docs/APPLICATION-MK.html
index 96d9241..31a12a1 100644
--- a/docs/APPLICATION-MK.html
+++ b/docs/APPLICATION-MK.html
@@ -149,6 +149,20 @@
     For the list of all supported ABIs and details about their usage and
     limitations, please read docs/CPU-ARCH-ABIS.html
 
+APP_STL
+    By default, the NDK build system provides C++ headers for the minimal
+    C++ runtime library (/system/lib/libstdc++.so) provided by the Android
+    system.
+
+    However, the NDK comes with alternative C++ implementations that you can
+    use or link to in your own applications. Define APP_STL to select one of
+    them. Examples are:
+
+       APP_STL := stlport_static    --> static STLport library
+       APP_STL := stlport_shared    --> shared STLport library
+       APP_STL := system            --> default C++ runtime library
+
+    For more information on the subject, please read docs/STL-SUPPORT.html
 
 A trivial Application.mk file would be:
 
diff --git a/docs/CHANGES.html b/docs/CHANGES.html
index 1ea6a63..cb09431 100644
--- a/docs/CHANGES.html
+++ b/docs/CHANGES.html
@@ -80,6 +80,11 @@
     Note that they still correspond to our minimal C++ runtime, no new feature
     was introduced here.
 
+- Add sources and prebuilt binaries for a port of the STLport C++ Standard
+  Library (www.stlport.org), and an easy way to use it at build time by
+  defining APP_STL in your Application.mk. See docs/APPLICATION-MK.html and
+  docs/STL-SUPPORT.html for all details.
+
 - Add support for prebuilt libraries with the PREBUILT_SHARED_LIBRARY and
   PREBUILT_STATIC_LIBRARIES build scripts. See the new documentation
   file named docs/PREBUILTS.html for explanations and usage examples.
diff --git a/docs/STL-SUPPORT.html b/docs/STL-SUPPORT.html
new file mode 100644
index 0000000..8335883
--- /dev/null
+++ b/docs/STL-SUPPORT.html
@@ -0,0 +1,93 @@
+<html><body><pre>
+C++ STL support with the Android NDK
+====================================
+
+
+The Android platform provides a very minimal C++ runtime support library
+(/system/lib/libstdc++) and corresponding headers for it in the NDK.
+
+If your C++ code needs a real Standard C++ Library, the NDK provides you
+with a port of the STLport library (www.stlport.org) and a way to use it
+easily in your applications.
+
+I. Usage:
+---------
+
+  Define APP_STL to name the C++ STL implementation you would want to use.
+  This instructs the NDK build system to automatically provide for the correct
+  headers and library dependencies for your C++ sources and modules.
+
+  Valid values are:
+
+     "system":         The default minimal C++ runtime support library
+     "stlport_static": STLport built as a static library.
+     "stlport_shared": STLport built as a shared library.
+
+  "stlport_shared" is preferred if you have several shared libraries in your
+  project that use the C++ STL, because it avoids duplication of functions
+  and more importantly of global variables (e.g. std::cout) in each one of
+  them, which can have surprising results.
+
+  On the other hand, you will have to load it explicitely when starting your
+  application, as in the following example:
+
+     static {
+         System.loadLibrary("stlport_shared");
+         System.loadLibrary("foo");
+         System.loadLibrary("bar");
+     }
+
+  Where both "libfoo.so" and "libbar.so" depend on "libstlport_shared.so".
+
+  Note that the shared library's name if "libstlport_shared.so" to avoid
+  naming conflicts with certain Android system images which include a
+  system-level libstlport.so (which happens to not be ABI-stable and
+  cannot be used from NDK-generated machine code).
+
+  "stlport_static" is preferred if you have only one shared library in your
+  project: only the STL functions and variables you actually need will be
+  linked to your machine code, reducing its code size, and you won't need
+  to load the dynamic stlport_shared at startup.
+
+  2/ Rebuild
+
+  After defining APP_STL, just rebuild your native code with $NDK/ndk-build
+  as usual.
+
+
+  3/ Debugging
+
+  The NDK provides prebuilt binaries of STLport to speed up development.
+  It can be however useful to rebuild the library from sources in order
+  to make native debugging easier. To do so, define the following in your
+  environment or your Application.mk before building:
+
+    STLPORT_FORCE_REBUILD := true
+
+
+II. Licensing:
+--------------
+
+  See sources/android/stlport/README for more information about the
+  STLport sources distributed with this SDK.
+
+  STLport is under a BSD-style open-source license.
+
+II. Known Issues:
+-----------------
+
+  - The STLport version provided with this NDK does not support C++ exceptions
+    and RTTI.
+
+  - No support for STLport in "standalone toolchain" mode.
+    (See docs/STANDALONE-TOOLCHAIN.html)
+
+
+III. Future Plans:
+------------------
+
+  - GNU libstdc++ support
+  - Exceptions and RTTI support
+  - uSTL support?
+
+</pre></body></html>
diff --git a/sources/android/stlport/Android.mk b/sources/android/stlport/Android.mk
index 96fc9d1..b0a6769 100644
--- a/sources/android/stlport/Android.mk
+++ b/sources/android/stlport/Android.mk
@@ -54,6 +54,11 @@
 libstlport_cppflags := -fuse-cxa-atexit
 libstlport_c_includes := $(libstlport_path)/stlport
 
+# Note: For now, this implementation depends on the system libstdc++
+#       We may want to avoid that in the future, i.e. in order to
+#       properly support exceptions and RTTI.
+libstlport_static_libs := libstdc++
+
 ifneq ($(STLPORT_FORCE_REBUILD),true)
 
 $(call ndk_log,Using prebuilt STLport libraries)
@@ -61,12 +66,14 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := stlport_static
 LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/lib$(LOCAL_MODULE).a
+LOCAL_STATIC_LIBRARIES := $(libstlport_static_libs)
 LOCAL_EXPORT_C_INCLUDES := $(libstlport_c_includes)
 include $(PREBUILT_STATIC_LIBRARY)
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := stlport_shared
 LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/lib$(LOCAL_MODULE).so
+LOCAL_STATIC_LIBRARIES := $(libstlport_static_libs)
 LOCAL_EXPORT_C_INCLUDES := $(libstlport_c_includes)
 include $(PREBUILT_SHARED_LIBRARY)
 
@@ -80,6 +87,7 @@
 LOCAL_CFLAGS := $(libstlport_cflags)
 LOCAL_CPPFLAGS := $(libstlport_cppflags)
 LOCAL_C_INCLUDES := $(libstlport_c_includes)
+LOCAL_STATIC_LIBRARIES := $(libstlport_static_libs)
 LOCAL_EXPORT_C_INCLUDES := $(libstlport_c_includes)
 include $(BUILD_STATIC_LIBRARY)
 
@@ -89,7 +97,11 @@
 LOCAL_CFLAGS := $(libstlport_cflags)
 LOCAL_CPPFLAGS := $(libstlport_cppflags)
 LOCAL_C_INCLUDES := $(libstlport_c_includes)
+LOCAL_STATIC_LIBRARIES := $(libstlport_static_libs)
 LOCAL_EXPORT_C_INCLUDES := $(libstlport_c_includes)
 include $(BUILD_SHARED_LIBRARY)
 
 endif # STLPORT_FORCE_REBUILD == true
+
+# See above not above libstdc++ dependency.
+$(call import-module,cxx-stl/system)
diff --git a/tests/device/test-stlport/jni/Android.mk b/tests/device/test-stlport/jni/Android.mk
index f8f5cb3..1acf6f7 100644
--- a/tests/device/test-stlport/jni/Android.mk
+++ b/tests/device/test-stlport/jni/Android.mk
@@ -20,8 +20,4 @@
 LOCAL_SRC_FILES := $(sources)
 LOCAL_SRC_FILES += unit/cppunit/test_main.cpp
 
-LOCAL_STATIC_LIBRARIES := stlport_static
 include $(BUILD_EXECUTABLE)
-
-$(call import-module,android/stlport)
-
diff --git a/tests/device/test-stlport/jni/Application.mk b/tests/device/test-stlport/jni/Application.mk
new file mode 100644
index 0000000..caf3b26
--- /dev/null
+++ b/tests/device/test-stlport/jni/Application.mk
@@ -0,0 +1 @@
+APP_STL := stlport_static