Implement module exports + update docs + add a sample.

Change-Id: Ib892ca7d46b69599ce4569d5929f0149bdea8e3f
diff --git a/build/core/build-binary.mk b/build/core/build-binary.mk
index 6582b1f..1de633b 100644
--- a/build/core/build-binary.mk
+++ b/build/core/build-binary.mk
@@ -34,6 +34,7 @@
 #
 $(call assert-defined,LOCAL_MAKEFILE)
 
+include $(BUILD_SYSTEM)/import-locals.mk
 include $(BUILD_SYSTEM)/build-module.mk
 
 # list of generated object files
diff --git a/build/core/definitions.mk b/build/core/definitions.mk
index 0d8ce50..501c322 100644
--- a/build/core/definitions.mk
+++ b/build/core/definitions.mk
@@ -171,7 +171,7 @@
     EXPORT_CFLAGS \
     EXPORT_CPPFLAGS \
     EXPORT_LDLIBS \
-    EXPORT_C_INCLUDES
+    EXPORT_C_INCLUDES \
 
 # The following are generated by the build scripts themselves
 modules-LOCALS += \
@@ -255,6 +255,30 @@
 module-is-installable    = $(call or,$(call module-is-type,$1,shared-library),$(call module-is-type,$1,executable))
 
 # -----------------------------------------------------------------------------
+# Function : module-get-export
+# Arguments: 1: module name
+#            2: export variable name without LOCAL_EXPORT_ prefix (e.g. 'CFLAGS')
+# Returns  : Exported value
+# Usage    : $(call module-get-export,<modulename>,<varname>)
+# Rationale: Return the recorded value of LOCAL_EXPORT_$2, if any, for module $1
+# -----------------------------------------------------------------------------
+module-get-export = $(__ndk_modules.$1.EXPORT_$2)
+
+# -----------------------------------------------------------------------------
+# Function : module-get-listed-export
+# Arguments: 1: list of module names
+#            2: export variable name without LOCAL_EXPORT_ prefix (e.g. 'CFLAGS')
+# Returns  : Exported values
+# Usage    : $(call module-get-listed-export,<module-list>,<varname>)
+# Rationale: Return the recorded value of LOCAL_EXPORT_$2, if any, for modules
+#            listed in $1.
+# -----------------------------------------------------------------------------
+module-get-listed-export = $(strip \
+    $(foreach __listed_module,$1,\
+        $(call module-get-export,$(__listed_module),$2)\
+    ))
+
+# -----------------------------------------------------------------------------
 # Function : modules-restore-locals
 # Arguments: 1: module name
 # Returns  : None
@@ -288,7 +312,7 @@
 #            Use module-get-static-dependencies to retrieve final list.
 # -----------------------------------------------------------------------------
 module-add-static-depends = \
-    $(call modules-add-depends-any,$1,$2,depends) \
+    $(call module-add-depends-any,$1,$2,depends) \
 
 # -----------------------------------------------------------------------------
 # Function : module-add-shared-depends
@@ -300,12 +324,12 @@
 #            Use modulge-get-shared-dependencies to retrieve final list.
 # -----------------------------------------------------------------------------
 module-add-shared-depends = \
-    $(call modules-add-depends-any,$1,$2,depends) \
+    $(call module-add-depends-any,$1,$2,depends) \
 
 # Used internally by module-add-static-depends and module-add-shared-depends
 # NOTE: this function must not modify the existing dependency order when new depends are added.
 #
-modules-add-depends-any = \
+module-add-depends-any = \
     $(eval __ndk_modules.$1.$3 += $(filter-out $(__ndk_modules.$1.$3),$(call strip-lib-prefix,$2)))
 
 # Used to recompute all dependencies once all module information has been recorded.
@@ -316,8 +340,8 @@
     )
 
 module-compute-depends = \
-    $(call modules-add-static-depends,$1,$(call strip-lib-prefix,$(__ndk_modules.$1.STATIC_LIBRARIES)))\
-    $(call modules-add-shared-depends,$1,$(call strip-lib-prefix,$(__ndk_modules.$1.SHARED_LIBRARIES)))
+    $(call module-add-static-depends,$1,$(call strip-lib-prefix,$(__ndk_modules.$1.STATIC_LIBRARIES)))\
+    $(call module-add-shared-depends,$1,$(call strip-lib-prefix,$(__ndk_modules.$1.SHARED_LIBRARIES)))
 
 module-get-installed = $(__ndk_modules.$1.INSTALLED)
 
diff --git a/build/core/import-locals.mk b/build/core/import-locals.mk
new file mode 100644
index 0000000..5e08b1a
--- /dev/null
+++ b/build/core/import-locals.mk
@@ -0,0 +1,61 @@
+# Copyright (C) 2009 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Handle local variable expor/import during the build
+#
+
+$(call assert-defined,LOCAL_MODULE)
+
+# For LOCAL_CFLAGS, LOCAL_CPPFLAGS and LOCAL_C_INCLUDES, we need
+# to use the exported definitions of the closure of all modules
+# we depend on.
+#
+# I.e. If module 'foo' depends on 'bar' which depends on 'zoo',
+# then 'foo' will get the CFLAGS/CPPFLAGS/C_INCLUDES of both 'bar'
+# and 'zoo'
+#
+
+#
+# The imported compiler flags are prepended to their LOCAL_XXXX value
+# (this allows the module to override them).
+#
+all_depends := $(call module-get-all-dependencies,$(LOCAL_MODULE))
+all_depends := $(filter-out $(LOCAL_MODULE),$(all_depends))
+
+imported_CFLAGS     := $(call module-get-listed-export,$(all_depends),CFLAGS)
+imported_CPPFLAGS   := $(call module-get-listed-export,$(all_depends),CPPFLAGS)
+imported_C_INCLUDES := $(call module-get-listed-export,$(all_depends),C_INCLUDES)
+
+ifdef NDK_DEBUG_IMPORTS
+    $(info Imports for module $(LOCAL_MODULE):)
+    $(info   CFLAGS='$(imported_CFLAGS)')
+    $(info   CPPFLAGS='$(imported_CPPFLAGS)')
+    $(info   C_INCLUDES='$(imported_C_INCLUDES)')
+    $(info All depends='$(all_depends)')
+endif
+
+LOCAL_CFLAGS     := $(strip $(imported_CFLAGS) $(LOCAL_CFLAGS))
+LOCAL_CPPFLAGS   := $(strip $(imported_CPPFLAGS) $(LOCAL_CPPFLAGS))
+LOCAL_C_INCLUDES := $(strip $(imported_C_INCLUDES) $(LOCAL_C_INCLUDES))
+
+# For LOCAL_LDLIBS, things are a bit different!
+#
+# You want the imported flags to appear _after_ the LOCAL_LDLIBS due to the way Unix
+# linkers work.
+#
+imported_LDLIBS := $(call module-get-listed-export,$(all_depends),LDLIBS)
+
+LOCAL_LDLIBS := $(strip $(LOCAL_LDLIBS) $(imported_LDLIBS))
+
+# We're done here
diff --git a/docs/ANDROID-MK.TXT b/docs/ANDROID-MK.TXT
index 3857385..397e12d 100644
--- a/docs/ANDROID-MK.TXT
+++ b/docs/ANDROID-MK.TXT
@@ -481,3 +481,70 @@
 
         http://en.wikipedia.org/wiki/NX_bit
         http://www.gentoo.org/proj/en/hardened/gnu-stack.xml
+
+LOCAL_EXPORT_CFLAGS
+    Define this variable to record a set of C/C++ compiler flags that will
+    be added to the LOCAL_CFLAGS definition of any other module that uses
+    this one with LOCAL_STATIC_LIBRARIES or LOCAL_SHARED_LIBRARIES.
+
+    For example, consider the module 'foo' with the following definition:
+
+        include $(CLEAR_VARS)
+        LOCAL_MODULE := foo
+        LOCAL_SRC_FILES := foo/foo.c
+        LOCAL_EXPORT_CFLAGS := -DFOO=1
+        include $(BUILD_STATIC_LIBRARY)
+
+    And another module, named 'bar' that depends on it as:
+
+        include $(CLEAR_VARS)
+        LOCAL_MODULE := bar
+        LOCAL_SRC_FILES := bar.c
+        LOCAL_CFLAGS := -DBAR=2
+        LOCAL_STATIC_LIBRARIES := foo
+        include $(BUILD_SHARED_LIBRARY)
+
+    Then, the flags '-DFOO=1 -DBAR=2' will be passed to the compiler when
+    building bar.c
+
+    Exported flags are prepended to your module's LOCAL_CFLAGS so you can
+    easily override them. They are also transitive: if 'zoo' depends on
+    'bar' which depends on 'foo', then 'zoo' will also inherit all flags
+    exported by 'foo'.
+
+    Finally, exported flags are *not* used when building the module that
+    exports them. In the above example, -DFOO=1 would not be passed to the
+    compiler when building foo/foo.c.
+
+LOCAL_EXPORT_CPPFLAGS
+    Same as LOCAL_EXPORT_CFLAGS, but for C++ flags only.
+
+LOCAL_EXPORT_C_INCLUDES
+    Same as LOCAL_EXPORT_CFLAGS, but for C include paths.
+    This can be useful if 'bar.c' wants to include headers
+    that are provided by module 'foo'.
+
+LOCAL_EXPORT_LDLIBS
+    Same as LOCAL_EXPORT_CFLAGS, but for linker flags. Note that the
+    imported linker flags will be appended to your module's LOCAL_LDLIBS
+    though, due to the way Unix linkers work.
+
+    This is typically useful when module 'foo' is a static library and has
+    code that depends on a system library. LOCAL_EXPORT_LDLIBS can then be
+    used to export the dependency. For example:
+
+        include $(CLEAR_VARS)
+        LOCAL_MODULE := foo
+        LOCAL_SRC_FILES := foo/foo.c
+        LOCAL_EXPORT_LDLIBS := -llog
+        include $(BUILD_STATIC_LIBRARY)
+
+        include $(CLEAR_VARS)
+        LOCAL_MODULE := bar
+        LOCAL_SRC_FILES := bar.c
+        LOCAL_STATIC_LIBRARIES := foo
+        include $(BUILD_SHARED_LIBRARY)
+
+    There, libbar.so will be built with a -llog at the end of the linker
+    command to indicate that it depends on the system logging library,
+    because it depends on 'foo'.
diff --git a/docs/CHANGES.TXT b/docs/CHANGES.TXT
index 202220f..88e8cbf 100644
--- a/docs/CHANGES.TXT
+++ b/docs/CHANGES.TXT
@@ -1,6 +1,24 @@
 Android NDK ChangeLog:
 
 -------------------------------------------------------------------------------
+android-ndk-r5
+
+IMPORTANT BUG FIXES:
+
+IMPORTANT CHANGES:
+
+- Support for module exports: A module can now define a set of compiler or
+  linker flags that will be automatically 'imported' by any other module that
+  depends on it, through LOCAL_STATIC_LIBRARIES or LOCAL_SHARED_LIBRARIES.
+
+  This is achieved with the help of new Android.mk variables named
+  LOCAL_EXPORT_CFLAGS, LOCAL_EXPORT_CPPFLAGS, LOCAL_EXPORT_C_INCLUDES and
+  LOCAL_EXPORT_LDLIBS. See docs/ANDROID-MK.TXT for mode documentation, and
+  a 'samples/module-exports' for a sample project that uses this.
+
+OTHER FIXES & CHANGES:
+
+-------------------------------------------------------------------------------
 android-ndk-r4b
 
 This release fixes a few bugs in r4 scripts. There are no new features.