• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1Android module paths (sharing code made easy):
2==============================================
3
4Starting from r5, the Android NDK comes with a cool feature that allows
5you to share and reuse other people's modules more easily.
6
7I. Overview:
8------------
9
10The main idea behind this feature are:
11
12  - You can install NDK modules outside of your main project source tree.
13  - You can easily 'import' them into your project with a one-line command.
14
15In practice, here's how this works:
16
17  1. Your NDK_MODULE_PATH environment variable will contain a list
18     of search paths on your system to lookup for modules.
19
20     It is up to you to set the variable, and to copy other modules
21     to the directories you listed in it.
22
23
24  2. To import a module, place a line like the following to, preferably at
25     the *end* of, your Android.mk:
26
27          $(call import-module,<tag>)
28
29     This will look for <tag>/Android.mk under any of the directories
30     listed in your NDK_MODULE_PATH.
31
32     (The reason why it must be at the end is to avoid messing with
33     the results of the 'my-dir' function. See its description in
34     docs/ANDROID-MK.html for details).
35
36
37  3. Declare that your project's modules depend on the imported one by
38     listing them in either your LOCAL_STATIC_LIBRARIES or
39     LOCAL_SHARED_LIBRARIES. For example:
40
41          LOCAL_STATIC_LIBRARIES += <tag>
42
43
44  4. Rebuild!
45
46     Remember that NDK r5 also added the ability for a module to "export"
47     declarations to other modules that depend on it (for example, see the
48     definition of LOCAL_EXPORT_CFLAGS in docs/ANDROID-MK.html).
49
50     A well-written module will correctly export all the things its
51     dependees need, et voila.
52
53
54Now for the full details:
55
56I. NDK_MODULE_PATH:
57-------------------
58
59The NDK_MODULE_PATH variable must contain a list of directories.
60
61  * Due to GNU Make limitations, NDK_MODULE_PATH must not contain any space.
62    The NDK will complain if this is not the case.
63
64  * Use ':' as the path separator.
65
66  * On Windows, use '/' as the directory separator.
67
68The directories of NDK_MODULE_PATH will be searched in order. The first
69<path>/<tag>/Android.mk file that is found during the lookup will be
70included automatically.
71
72
73As a convenience, $NDK/sources is appended to your NDK_MODULE_PATH
74definition by the NDK build system. This allows you to easily import
75the helper libraries that come with it (see docs/CPU-FEATURES.html for
76a practical example).
77
78
79II. Writing an import module:
80-----------------------------
81
82Writing an import module is trivial and very similar to what you do when
83writing project modules:
84
85  1. Create a sub-directory from one of your NDK_MODULE_PATH directories.
86
87    For example, if NDK_MODULE_PATH is defined to /home/user/ndk-modules,
88    then create the directory /home/user/ndk-modules/my-module/
89
90
91  2. Place an Android.mk and eventual source code there.
92
93    Just like you would for a project module, where these files normally
94    go to $PROJECT_PATH/Android.mk. In the example above, this would go
95    to /home/user/ndk-modules/my-module/Android.mk
96
97    NOTE: Any Application.mk file here will be ignored.
98
99
100  3. Any module that depends on your new module, would import by calling
101    the import-module function. For example:
102
103          $(call import-module,my-first-module)
104
105
106Import modules *can* import other modules, but circular dependencies are
107not permitted and will be detected. Dependencies are transitive and the build
108system will compute all the things that need to be built for you.
109
110The NDK build system will not place object files or executables in your
111import module directory (they will all be placed under the project's
112build directory, e.g. $PROJECT_PATH/obj/).
113
114You can however distribute prebuilt binaries in your import module with
115the new PREBUILT_STATIC_LIBRARIES or PREBUILT_SHARED_LIBRARIES feature
116(see docs/ANDROID-MK.html).
117
118This makes it easy to package and redistribute your import module directory
119to third-parties.
120
121
122III. Naming an import module:
123-----------------------------
124
125It is important to understand a few things related to the naming of
126your import module:
127
128  - What 'import-module' does is really search for a file named Android.mk
129    using the list provided by NDK_MODULE_PATH, then include while performing
130    very little bit of house-keeping.
131
132    Your imported Android.mk can define any number of modules, with
133    any name. As a consequence, there is no direct relationship between
134    <name> in the following line:
135
136          $(call import-module,<tag>/<name>)
137
138    And the names of the modules defined under <tag>/<name>/Android.mk.
139
140    IN CASE OF DOUBT, KEEP IT SIMPLE!
141
142    If you only plan to provide one import module, just name it like the
143    base import directory.
144
145    On the other hand, you may want to provide a static and a shared
146    version of your module: use distinct names under the same top-level
147    Android.mk. Consider the following build script:
148
149        $NDK_MODULE_PATH/foo/bar/Android.mk:
150
151           LOCAL_PATH := $(call my-dir)
152
153           # Static version of the library is named 'bar_static'
154           include $(CLEAR_VARS)
155           LOCAL_MODULE := bar_static
156           LOCAL_SRC_FILES := bar.c
157           # Ensure our dependees can include <bar.h> too
158           LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
159           include $(BUILD_STATIC_LIBRARY)
160
161           # Shared version of the library is named 'bar_shared'
162           LOCAL_MODULE := bar_shared
163           LOCAL_SRC_FILES := bar.c
164           LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
165           include $(BUILD_SHARED_LIBRARY)
166
167    Another module would refer to it by doing the following:
168
169         1. Import 'foo/bar', as in:
170
171                  $(call import-module,foo/bar)
172
173         2. To use the static library:
174
175                ...
176                LOCAL_STATIC_LIBRARIES := bar_static
177
178         3. Or to use the shared library:
179
180                ...
181                LOCAL_SHARED_LIBRARIES := bar_shared
182
183
184   - The module namespace is flat, so try to give your modules names that
185     are likely to not collide with other. Note that your can use
186     LOCAL_MODULE_FILENAME to give the name of your module's binary
187     file, independently from its LOCAL_MODULE (see docs/ANDROID-MK.html
188     for definition and usage). For example:
189
190             include $(CLEAR_VARS)
191             LOCAL_MODULE := super_foo
192             LOCAL_MODULE_FILENAME := foo   # will give libfoo.so
193             LOCAL_SRC_FILES := foo-src.c
194             LOCAL_CFLAGS := -DVOLUME=11
195             include $(BUILD_SHARED_LIBRARY)
196
197             include $(CLEAR_VARS)
198             LOCAL_MODULE := normal_foo
199             LOCAL_MODULE_FILENAME := foo   # will also give libfoo.so
200             LOCAL_SRC_FILES := foo-src.c
201             include $(BUILD_SHARED_LIBRARY)
202
203      Defines two modules named "super_foo" and "normal_foo"
204      which both produce a shared library named 'libfoo.so'
205
206      As a consequence, only one of them can be used by your project or
207      a conflict will happen at build time. This allows you to select either
208      the normal or optimized version in your NDK build scripts, while
209      keeping the same simple loading instruction in your Java sources as:
210
211            static {
212                System.loadLibrary("foo");
213            }
214
215
216IV. Tips & Recommendations:
217---------------------------
218
219* You don't need to import a module before you can reference it!
220
221* Use import-module at the *end* of your Android.mk to avoid messing with
222  the result of 'my-dir'. See the description of this function in
223  docs/ANDROID-MK.html to understand why.
224
225* It is *strongly* suggested to use a subdirectory for your import tags,
226  that describes its origin, as in:
227
228        $(call import-module,gtk/glib)
229
230> or something like:
231
232          $(call import-module,com.example/awesomelib)
233
234  IMPORTANT: THE 'android' IMPORT DIRECTORY, AND ANY OF ITS SUB-DIRECTORIES
235             IS *RESERVED* FOR NDK USAGE. FEEL FREE TO ORGANIZE YOUR OTHER
236             IMPORT MODULES AS YOU WANT OTHERWISE.
237