| <html><body><pre>Android module paths (sharing code made easy): |
| ============================================== |
| |
| Starting from r5, the Android NDK comes with a cool feature that allows |
| you to share and reuse other people's modules more easily. |
| |
| I. Overview: |
| ------------ |
| |
| The main idea behind this feature are: |
| |
| - You can install NDK modules outside of your main project source tree. |
| - You can easily 'import' them into your project with a one-line command. |
| |
| In practice, here's how this works: |
| |
| 1. Your NDK_MODULE_PATH environment variable will contain a list |
| of search paths on your system to lookup for modules. |
| |
| It is up to you to set the variable, and to copy other modules |
| to the directories you listed in it. |
| |
| |
| 2. To import a module, place a line like the following to, preferably at |
| the *end* of, your Android.mk: |
| |
| $(call import-module,<tag>) |
| |
| This will look for <tag>/Android.mk under any of the directories |
| listed in your NDK_MODULE_PATH. |
| |
| (The reason why it must be at the end is to avoid messing with |
| the results of the 'my-dir' function. See its description in |
| docs/ANDROID-MK.html for details). |
| |
| |
| 3. Declare that your project's modules depend on the imported one by |
| listing them in either your LOCAL_STATIC_LIBRARIES or |
| LOCAL_SHARED_LIBRARIES. For example: |
| |
| LOCAL_STATIC_LIBRARIES += <tag> |
| |
| |
| 4. Rebuild! |
| |
| Remember that NDK r5 also added the ability for a module to "export" |
| declarations to other modules that depend on it (for example, see the |
| definition of LOCAL_EXPORT_CFLAGS in docs/ANDROID-MK.html). |
| |
| A well-written module will correctly export all the things its |
| dependees need, et voila. |
| |
| |
| Now for the full details: |
| |
| I. NDK_MODULE_PATH: |
| ------------------- |
| |
| The NDK_MODULE_PATH variable must contain a list of directories. |
| |
| * Due to GNU Make limitations, NDK_MODULE_PATH must not contain any space. |
| The NDK will complain if this is not the case. |
| |
| * Use ':' as the path separator. |
| |
| * On Windows, use '/' as the directory separator. |
| |
| The directories of NDK_MODULE_PATH will be searched in order. The first |
| <path>/<tag>/Android.mk file that is found during the lookup will be |
| included automatically. |
| |
| |
| As a convenience, $NDK/sources is appended to your NDK_MODULE_PATH |
| definition by the NDK build system. This allows you to easily import |
| the helper libraries that come with it (see docs/CPU-FEATURES.html for |
| a practical example). |
| |
| |
| II. Writing an import module: |
| ----------------------------- |
| |
| Writing an import module is trivial and very similar to what you do when |
| writing project modules: |
| |
| 1. Create a sub-directory from one of your NDK_MODULE_PATH directories. |
| |
| For example, if NDK_MODULE_PATH is defined to /home/user/ndk-modules, |
| then create the directory /home/user/ndk-modules/my-module/ |
| |
| |
| 2. Place an Android.mk and eventual source code there. |
| |
| Just like you would for a project module, where these files normally |
| go to $PROJECT_PATH/Android.mk. In the example above, this would go |
| to /home/user/ndk-modules/my-module/Android.mk |
| |
| NOTE: Any Application.mk file here will be ignored. |
| |
| |
| 3. Any module that depends on your new module, would import by calling |
| the import-module function. For example: |
| |
| $(call import-module,my-first-module) |
| |
| |
| Import modules *can* import other modules, but circular dependencies are |
| not permitted and will be detected. Dependencies are transitive and the build |
| system will compute all the things that need to be built for you. |
| |
| The NDK build system will not place object files or executables in your |
| import module directory (they will all be placed under the project's |
| build directory, e.g. $PROJECT_PATH/obj/). |
| |
| You can however distribute prebuilt binaries in your import module with |
| the new PREBUILT_STATIC_LIBRARIES or PREBUILT_SHARED_LIBRARIES feature |
| (see docs/ANDROID-MK.html). |
| |
| This makes it easy to package and redistribute your import module directory |
| to third-parties. |
| |
| |
| III. Naming an import module: |
| ----------------------------- |
| |
| It is important to understand a few things related to the naming of |
| your import module: |
| |
| - What 'import-module' does is really search for a file named Android.mk |
| using the list provided by NDK_MODULE_PATH, then include while performing |
| very little bit of house-keeping. |
| |
| Your imported Android.mk can define any number of modules, with |
| any name. As a consequence, there is no direct relationship between |
| <name> in the following line: |
| |
| $(call import-module,<tag>/<name>) |
| |
| And the names of the modules defined under <tag>/<name>/Android.mk. |
| |
| IN CASE OF DOUBT, KEEP IT SIMPLE! |
| |
| If you only plan to provide one import module, just name it like the |
| base import directory. |
| |
| On the other hand, you may want to provide a static and a shared |
| version of your module: use distinct names under the same top-level |
| Android.mk. Consider the following build script: |
| |
| $NDK_MODULE_PATH/foo/bar/Android.mk: |
| |
| LOCAL_PATH := $(call my-dir) |
| |
| # Static version of the library is named 'bar_static' |
| include $(CLEAR_VARS) |
| LOCAL_MODULE := bar_static |
| LOCAL_SRC_FILES := bar.c |
| # Ensure our dependees can include <bar.h> too |
| LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) |
| include $(BUILD_STATIC_LIBRARY) |
| |
| # Shared version of the library is named 'bar_shared' |
| LOCAL_MODULE := bar_shared |
| LOCAL_SRC_FILES := bar.c |
| LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) |
| include $(BUILD_SHARED_LIBRARY) |
| |
| Another module would refer to it by doing the following: |
| |
| 1. Import 'foo/bar', as in: |
| |
| $(call import-module,foo/bar) |
| |
| 2. To use the static library: |
| |
| ... |
| LOCAL_STATIC_LIBRARIES := bar_static |
| |
| 3. Or to use the shared library: |
| |
| ... |
| LOCAL_SHARED_LIBRARIES := bar_shared |
| |
| |
| - The module namespace is flat, so try to give your modules names that |
| are likely to not collide with other. Note that your can use |
| LOCAL_MODULE_FILENAME to give the name of your module's binary |
| file, independently from its LOCAL_MODULE (see docs/ANDROID-MK.html |
| for definition and usage). For example: |
| |
| include $(CLEAR_VARS) |
| LOCAL_MODULE := super_foo |
| LOCAL_MODULE_FILENAME := foo # will give libfoo.so |
| LOCAL_SRC_FILES := foo-src.c |
| LOCAL_CFLAGS := -DVOLUME=11 |
| include $(BUILD_SHARED_LIBRARY) |
| |
| include $(CLEAR_VARS) |
| LOCAL_MODULE := normal_foo |
| LOCAL_MODULE_FILENAME := foo # will also give libfoo.so |
| LOCAL_SRC_FILES := foo-src.c |
| include $(BUILD_SHARED_LIBRARY) |
| |
| Defines two modules named "super_foo" and "normal_foo" |
| which both produce a shared library named 'libfoo.so' |
| |
| As a consequence, only one of them can be used by your project or |
| a conflict will happen at build time. This allows you to select either |
| the normal or optimized version in your NDK build scripts, while |
| keeping the same simple loading instruction in your Java sources as: |
| |
| static { |
| System.loadLibrary("foo"); |
| } |
| |
| |
| IV. Tips & Recommendations: |
| --------------------------- |
| |
| * You don't need to import a module before you can reference it! |
| |
| * Use import-module at the *end* of your Android.mk to avoid messing with |
| the result of 'my-dir'. See the description of this function in |
| docs/ANDROID-MK.html to understand why. |
| |
| * It is *strongly* suggested to use a subdirectory for your import tags, |
| that describes its origin, as in: |
| |
| $(call import-module,gtk/glib) |
| |
| or something like: |
| |
| $(call import-module,com.example/awesomelib) |
| |
| IMPORTANT: THE 'android' IMPORT DIRECTORY, AND ANY OF ITS SUB-DIRECTORIES |
| IS *RESERVED* FOR NDK USAGE. FEEL FREE TO ORGANIZE YOUR OTHER |
| IMPORT MODULES AS YOU WANT OTHERWISE. |
| </pre></body></html> |