1 <html><body><pre>Android module paths (sharing code made easy): 2 ============================================== 3 4 Starting from r5, the Android NDK comes with a cool feature that allows 5 you to share and reuse other people's modules more easily. 6 7 I. Overview: 8 ------------ 9 10 The 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 15 In 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 54 Now for the full details: 55 56 I. NDK_MODULE_PATH: 57 ------------------- 58 59 The 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 68 The 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 70 included automatically. 71 72 73 As a convenience, $NDK/sources is appended to your NDK_MODULE_PATH 74 definition by the NDK build system. This allows you to easily import 75 the helper libraries that come with it (see docs/CPU-FEATURES.html for 76 a practical example). 77 78 79 II. Writing an import module: 80 ----------------------------- 81 82 Writing an import module is trivial and very similar to what you do when 83 writing 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 106 Import modules *can* import other modules, but circular dependencies are 107 not permitted and will be detected. Dependencies are transitive and the build 108 system will compute all the things that need to be built for you. 109 110 The NDK build system will not place object files or executables in your 111 import module directory (they will all be placed under the project's 112 build directory, e.g. $PROJECT_PATH/obj/). 113 114 You can however distribute prebuilt binaries in your import module with 115 the new PREBUILT_STATIC_LIBRARIES or PREBUILT_SHARED_LIBRARIES feature 116 (see docs/ANDROID-MK.html). 117 118 This makes it easy to package and redistribute your import module directory 119 to third-parties. 120 121 122 III. Naming an import module: 123 ----------------------------- 124 125 It is important to understand a few things related to the naming of 126 your 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 216 IV. 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 </pre></body></html>