@@ -10,13 +10,13 @@ def __init__(self, text=None):
10
10
def __str__ (self ):
11
11
return "ERROR" if self .t is None else self .t
12
12
13
- def execute (cmd , shell = False ):
13
+ def execute (cmd , shell = False , allowFail = False ):
14
14
try :
15
15
log .info ("Executing: %s" % cmd )
16
16
retcode = subprocess .call (cmd , shell = shell )
17
17
if retcode < 0 :
18
18
raise Fail ("Child was terminated by signal:" % s - retcode )
19
- elif retcode > 0 :
19
+ elif retcode > 0 and not allowFail :
20
20
raise Fail ("Child returned: %s" % retcode )
21
21
except OSError as e :
22
22
raise Fail ("Execution failed: %d / %s" % (e .errno , e .strerror ))
@@ -45,44 +45,37 @@ def check_dir(d, create=False, clean=False):
45
45
os .makedirs (d )
46
46
return d
47
47
48
- def determine_engine_version (manifest_path ):
49
- with open (manifest_path , "rt" ) as f :
50
- return re .search (r'android:versionName="(\d+\.\d+)"' , f .read (), re .MULTILINE ).group (1 )
51
-
52
48
def determine_opencv_version (version_hpp_path ):
53
49
# version in 2.4 - CV_VERSION_EPOCH.CV_VERSION_MAJOR.CV_VERSION_MINOR.CV_VERSION_REVISION
54
50
# version in master - CV_VERSION_MAJOR.CV_VERSION_MINOR.CV_VERSION_REVISION-CV_VERSION_STATUS
55
51
with open (version_hpp_path , "rt" ) as f :
56
52
data = f .read ()
53
+ epoch = re .search (r'^#define\W+CV_VERSION_EPOCH\W+(\d+)$' , data , re .MULTILINE ).group (1 )
57
54
major = re .search (r'^#define\W+CV_VERSION_MAJOR\W+(\d+)$' , data , re .MULTILINE ).group (1 )
58
55
minor = re .search (r'^#define\W+CV_VERSION_MINOR\W+(\d+)$' , data , re .MULTILINE ).group (1 )
59
56
revision = re .search (r'^#define\W+CV_VERSION_REVISION\W+(\d+)$' , data , re .MULTILINE ).group (1 )
60
- version_status = re . search ( r'^#define\W+CV_VERSION_STATUS\W+"([^"]*)"$' , data , re . MULTILINE ). group ( 1 )
61
- return "%(major )s.%(minor )s.%(revision )s%(version_status )s" % locals ()
57
+ revision = '' if revision == '0' else '.' + revision
58
+ return "%(epoch )s.%(major )s.%(minor )s%(revision )s" % locals ()
62
59
63
60
#===================================================================================================
64
61
65
62
class ABI :
66
- def __init__ (self , platform_id , name , toolchain , cmake_name = None ):
63
+ def __init__ (self , platform_id , name , toolchain , api_level = 8 , cmake_name = None ):
67
64
self .platform_id = platform_id # platform code to add to apk version (for cmake)
68
65
self .name = name # general name (official Android ABI identifier)
69
66
self .toolchain = toolchain # toolchain identifier (for cmake)
67
+ self .api_level = api_level
70
68
self .cmake_name = cmake_name # name of android toolchain (for cmake)
71
69
if self .cmake_name is None :
72
70
self .cmake_name = self .name
73
71
def __str__ (self ):
74
72
return "%s (%s)" % (self .name , self .toolchain )
75
- def haveIPP (self ):
76
- return self .name == "x86" or self .name == "x86_64"
77
73
78
74
ABIs = [
79
- ABI ("2" , "armeabi-v7a" , "arm-linux-androideabi-4.8" , cmake_name = "armeabi-v7a with NEON" ),
80
- ABI ("1" , "armeabi" , "arm-linux-androideabi-4.8" ),
81
- ABI ("3" , "arm64-v8a" , "aarch64-linux-android-4.9" ),
82
- ABI ("5" , "x86_64" , "x86_64-4.9" ),
83
- ABI ("4" , "x86" , "x86-4.8" ),
84
- ABI ("7" , "mips64" , "mips64el-linux-android-4.9" ),
85
- ABI ("6" , "mips" , "mipsel-linux-android-4.8" )
75
+ ABI ("2" , "armeabi-v7a" , "arm-linux-androideabi-4.6" , cmake_name = "armeabi-v7a with NEON" ),
76
+ ABI ("1" , "armeabi" , "arm-linux-androideabi-4.6" ),
77
+ ABI ("4" , "x86" , "x86-clang3.1" , api_level = 9 ),
78
+ ABI ("6" , "mips" , "mipsel-linux-android-4.6" , api_level = 9 )
86
79
]
87
80
88
81
#===================================================================================================
@@ -91,107 +84,59 @@ class Builder:
91
84
def __init__ (self , workdir , opencvdir ):
92
85
self .workdir = check_dir (workdir , create = True )
93
86
self .opencvdir = check_dir (opencvdir )
94
- self .extra_modules_path = None
95
87
self .libdest = check_dir (os .path .join (self .workdir , "o4a" ), create = True , clean = True )
96
88
self .docdest = check_dir (os .path .join (self .workdir , "javadoc" ), create = True , clean = True )
97
89
self .resultdest = check_dir (os .path .join (self .workdir , "OpenCV-android-sdk" ), create = True , clean = True )
98
- self .extra_packs = []
99
90
self .opencv_version = determine_opencv_version (os .path .join (self .opencvdir , "modules" , "core" , "include" , "opencv2" , "core" , "version.hpp" ))
100
- self .engine_version = determine_engine_version (os .path .join (self .opencvdir , "platforms" , "android" , "service" , "engine" , "AndroidManifest.xml" ))
101
91
self .use_ccache = True
102
92
103
93
def get_toolchain_file (self ):
104
94
return os .path .join (self .opencvdir , "platforms" , "android" , "android.toolchain.cmake" )
105
95
106
- def get_engine_apk_dest (self , engdest ):
107
- return os .path .join (engdest , "platforms" , "android" , "service" , "engine" , ".build" )
108
-
109
- def add_extra_pack (self , ver , path ):
110
- if path is None :
111
- return
112
- self .extra_packs .append ((ver , check_dir (path )))
113
-
114
96
def clean_library_build_dir (self ):
115
97
for d in ["CMakeCache.txt" , "CMakeFiles/" , "bin/" , "libs/" , "lib/" , "package/" , "install/samples/" ]:
116
98
rm_one (d )
117
99
118
- def build_library (self , abi , do_install ):
100
+ def build_library (self , abi , do_install , build_docs ):
119
101
cmd = [
120
102
"cmake" ,
121
103
"-GNinja" ,
122
104
"-DCMAKE_TOOLCHAIN_FILE='%s'" % self .get_toolchain_file (),
123
- "-DWITH_OPENCL=OFF" ,
124
- "-DWITH_CUDA=OFF" ,
125
- "-DWITH_IPP=%s" % ("ON" if abi .haveIPP () else "OFF" ),
105
+ "-DINSTALL_CREATE_DISTRIB=ON" ,
106
+ #"-DWITH_OPENCL=OFF",
107
+ "-DWITH_CUDA=OFF" , "-DBUILD_opencv_gpu=OFF" ,
108
+ "-DBUILD_opencv_nonfree=OFF" ,
109
+ "-DWITH_TBB=OFF" ,
110
+ "-DWITH_IPP=OFF" ,
126
111
"-DBUILD_EXAMPLES=OFF" ,
127
112
"-DBUILD_TESTS=OFF" ,
128
113
"-DBUILD_PERF_TESTS=OFF" ,
129
114
"-DBUILD_DOCS=OFF" ,
130
115
"-DBUILD_ANDROID_EXAMPLES=ON" ,
131
116
"-DINSTALL_ANDROID_EXAMPLES=ON" ,
132
117
"-DANDROID_STL=gnustl_static" ,
133
- "-DANDROID_NATIVE_API_LEVEL=9" ,
118
+ "-DANDROID_NATIVE_API_LEVEL=%s" % abi . api_level ,
134
119
"-DANDROID_ABI='%s'" % abi .cmake_name ,
135
- "-DWITH_TBB=ON" ,
136
120
"-DANDROID_TOOLCHAIN_NAME=%s" % abi .toolchain
137
121
]
138
122
139
- if self .extra_modules_path is not None :
140
- cmd .append ("-DOPENCV_EXTRA_MODULES_PATH='%s'" % self .extra_modules_path )
141
-
142
123
cmd .append (self .opencvdir )
143
124
144
125
if self .use_ccache == True :
145
126
cmd .append ("-DNDK_CCACHE=ccache" )
146
127
if do_install :
147
128
cmd .extend (["-DBUILD_TESTS=ON" , "-DINSTALL_TESTS=ON" ])
129
+ if do_install and build_docs :
130
+ cmd .extend (["-DBUILD_DOCS=ON" ])
148
131
execute (cmd )
149
132
if do_install :
150
- execute (["ninja" ])
151
- for c in ["libs" , "dev" , "java" , "samples" ]:
133
+ execute (["cmake" , "--build" , "." ])
134
+ if do_install and build_docs :
135
+ execute (["cmake" , "--build" , "." , "--target" , "docs" ])
136
+ for c in ["libs" , "dev" , "java" , "samples" ] + (["docs" ] if do_install and build_docs else []):
152
137
execute (["cmake" , "-DCOMPONENT=%s" % c , "-P" , "cmake_install.cmake" ])
153
138
else :
154
- execute (["ninja" , "install/strip" ])
155
-
156
- def build_engine (self , abi , engdest ):
157
- cmd = [
158
- "cmake" ,
159
- "-GNinja" ,
160
- "-DCMAKE_TOOLCHAIN_FILE='%s'" % self .get_toolchain_file (),
161
- "-DANDROID_ABI='%s'" % abi .cmake_name ,
162
- "-DBUILD_ANDROID_SERVICE=ON" ,
163
- "-DANDROID_PLATFORM_ID=%s" % abi .platform_id ,
164
- "-DWITH_CUDA=OFF" ,
165
- "-DWITH_OPENCL=OFF" ,
166
- "-DWITH_IPP=OFF" ,
167
- self .opencvdir
168
- ]
169
- execute (cmd )
170
- apkdest = self .get_engine_apk_dest (engdest )
171
- # Add extra data
172
- apkxmldest = check_dir (os .path .join (apkdest , "res" , "xml" ), create = True )
173
- apklibdest = check_dir (os .path .join (apkdest , "libs" , abi .name ), create = True )
174
- for ver , d in self .extra_packs + [("3.1.0" , os .path .join (self .libdest , "lib" ))]:
175
- r = ET .Element ("library" , attrib = {"version" : ver })
176
- log .info ("Adding libraries from %s" , d )
177
-
178
- for f in glob .glob (os .path .join (d , abi .name , "*.so" )):
179
- log .info ("Copy file: %s" , f )
180
- shutil .copy2 (f , apklibdest )
181
- if "libnative_camera" in f :
182
- continue
183
- log .info ("Register file: %s" , os .path .basename (f ))
184
- n = ET .SubElement (r , "file" , attrib = {"name" : os .path .basename (f )})
185
-
186
- if len (list (r )) > 0 :
187
- xmlname = os .path .join (apkxmldest , "config%s.xml" % ver .replace ("." , "" ))
188
- log .info ("Generating XML config: %s" , xmlname )
189
- ET .ElementTree (r ).write (xmlname , encoding = "utf-8" )
190
-
191
- execute (["ninja" , "opencv_engine" ])
192
- execute (["ant" , "-f" , os .path .join (apkdest , "build.xml" ), "debug" ],
193
- shell = (sys .platform == 'win32' ))
194
- # TODO: Sign apk
139
+ execute (["cmake" , "--build" , "." , "--target" , "install/strip" ])
195
140
196
141
def build_javadoc (self ):
197
142
classpaths = [os .path .join (self .libdest , "bin" , "classes" )]
@@ -201,6 +146,7 @@ def build_javadoc(self):
201
146
classpaths .append (os .path .join (dir , f ))
202
147
cmd = [
203
148
"javadoc" ,
149
+ "-encoding" , "UTF-8" ,
204
150
"-header" , "OpenCV %s" % self .opencv_version ,
205
151
"-nodeprecated" ,
206
152
"-footer" , '<a href="http://docs.opencv.org">OpenCV %s Documentation</a>' % self .opencv_version ,
@@ -211,9 +157,9 @@ def build_javadoc(self):
211
157
]
212
158
for _ , dirs , _ in os .walk (os .path .join (self .libdest , "src" , "org" , "opencv" )):
213
159
cmd .extend (["org.opencv." + d for d in dirs ])
214
- execute (cmd )
160
+ execute (cmd , allowFail = True ) # FIXIT javadoc currenly reports some errors
215
161
216
- def gather_results (self , engines ):
162
+ def gather_results (self , with_samples_apk ):
217
163
# Copy all files
218
164
root = os .path .join (self .libdest , "install" )
219
165
for item in os .listdir (root ):
@@ -226,13 +172,6 @@ def gather_results(self, engines):
226
172
log .info ("Copy file: %s" , item )
227
173
shutil .copy2 (item , os .path .join (self .resultdest , name ))
228
174
229
- # Copy engines for all platforms
230
- for abi , engdest in engines :
231
- log .info ("Copy engine: %s (%s)" , abi , engdest )
232
- f = os .path .join (self .get_engine_apk_dest (engdest ), "bin" , "opencv_engine-debug.apk" )
233
- resname = "OpenCV_%s_Manager_%s_%s.apk" % (self .opencv_version , self .engine_version , abi )
234
- shutil .copy2 (f , os .path .join (self .resultdest , "apk" , resname ))
235
-
236
175
# Copy javadoc
237
176
log .info ("Copy docs: %s" , self .docdest )
238
177
shutil .copytree (self .docdest , os .path .join (self .resultdest , "sdk" , "java" , "javadoc" ))
@@ -244,6 +183,9 @@ def gather_results(self, engines):
244
183
if os .path .isdir (item ):
245
184
for name in ["build.xml" , "local.properties" , "proguard-project.txt" ]:
246
185
rm_one (os .path .join (item , name ))
186
+ if not with_samples_apk :
187
+ if re .search (r'\.apk$' , item ): # reduce size of SDK
188
+ rm_one (item )
247
189
248
190
249
191
#===================================================================================================
@@ -254,11 +196,10 @@ def gather_results(self, engines):
254
196
parser .add_argument ("opencv_dir" , help = "Path to OpenCV source dir" )
255
197
parser .add_argument ('--ndk_path' , help = "Path to Android NDK to use for build" )
256
198
parser .add_argument ('--sdk_path' , help = "Path to Android SDK to use for build" )
257
- parser .add_argument ("--extra_modules_path" , help = "Path to extra modules to use for build" )
258
- parser .add_argument ('--sign_with' , help = "Sertificate to sign the Manager apk" )
259
- parser .add_argument ('--build_doc' , action = "store_true" , help = "Build javadoc" )
199
+ parser .add_argument ('--build_doc' , action = "store_true" , help = "Build documentation" )
200
+ parser .add_argument ('--build_javadoc' , action = "store_true" , help = "Build javadoc" )
260
201
parser .add_argument ('--no_ccache' , action = "store_true" , help = "Do not use ccache during library build" )
261
- parser .add_argument ('--extra_pack ' , action = 'append' , help = "provide extra OpenCV libraries for Manager apk in form <version>:<path-to-native-libs>, for example '2.4.11:unpacked/sdk/native/libs' " )
202
+ parser .add_argument ('--with_samples_apk ' , action = "store_true" , help = "Include samples APKs " )
262
203
args = parser .parse_args ()
263
204
264
205
log .basicConfig (format = '%(message)s' , level = log .DEBUG )
@@ -274,48 +215,26 @@ def gather_results(self, engines):
274
215
275
216
builder = Builder (args .work_dir , args .opencv_dir )
276
217
277
- if args .extra_modules_path is not None :
278
- builder .extra_modules_path = os .path .abspath (args .extra_modules_path )
279
-
280
218
if args .no_ccache :
281
219
builder .use_ccache = False
282
220
283
221
log .info ("Detected OpenCV version: %s" , builder .opencv_version )
284
- log .info ("Detected Engine version: %s" , builder .engine_version )
285
222
286
- if args .extra_pack :
287
- for one in args .extra_pack :
288
- i = one .find (":" )
289
- if i > 0 and i < len (one ) - 1 :
290
- builder .add_extra_pack (one [:i ], one [i + 1 :])
291
- else :
292
- raise Fail ("Bad extra pack provided: %s, should be in form '<version>:<path-to-native-libs>'" % one )
293
-
294
- engines = []
295
223
for i , abi in enumerate (ABIs ):
296
224
do_install = (i == 0 )
297
- engdest = check_dir (os .path .join (builder .workdir , "build_service_%s" % abi .name ), create = True , clean = True )
298
225
299
226
log .info ("=====" )
300
227
log .info ("===== Building library for %s" , abi )
301
228
log .info ("=====" )
302
229
303
230
os .chdir (builder .libdest )
304
231
builder .clean_library_build_dir ()
305
- builder .build_library (abi , do_install )
306
-
307
- log .info ("=====" )
308
- log .info ("===== Building engine for %s" , abi )
309
- log .info ("=====" )
310
-
311
- os .chdir (engdest )
312
- builder .build_engine (abi , engdest )
313
- engines .append ((abi .name , engdest ))
232
+ builder .build_library (abi , do_install , build_docs = args .build_doc )
314
233
315
- if args .build_doc :
234
+ if args .build_doc or args . build_javadoc :
316
235
builder .build_javadoc ()
317
236
318
- builder .gather_results (engines )
237
+ builder .gather_results (with_samples_apk = args . with_samples_apk )
319
238
320
239
log .info ("=====" )
321
240
log .info ("===== Build finished" )
0 commit comments