7d65e81ef55178de10716dcd27099e804dfffd01
[platform/framework/web/crosswalk.git] / src / xwalk / build / android / generate_xwalk_core_library.py
1 #!/usr/bin/env python
2 #
3 # Copyright (c) 2013 Intel Corporation. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
6 # pylint: disable=F0401
7
8 import distutils.dir_util
9 import optparse
10 import os
11 import shutil
12 import sys
13 from common_function import RemoveUnusedFilesInReleaseMode
14 from xml.dom.minidom import Document
15
16 LIBRARY_PROJECT_NAME = 'xwalk_core_library'
17 XWALK_CORE_SHELL_APK = 'xwalk_core_shell_apk'
18
19 def AddGeneratorOptions(option_parser):
20   option_parser.add_option('-s', dest='source',
21                            help='Source directory of project root.',
22                            type='string')
23   option_parser.add_option('-t', dest='target',
24                            help='Product out target directory.',
25                            type='string')
26
27
28 def CleanLibraryProject(out_dir):
29   out_project_path = os.path.join(out_dir, LIBRARY_PROJECT_NAME)
30   if os.path.exists(out_project_path):
31     for item in os.listdir(out_project_path):
32       sub_path = os.path.join(out_project_path, item)
33       if os.path.isdir(sub_path):
34         shutil.rmtree(sub_path)
35       elif os.path.isfile(sub_path):
36         os.remove(sub_path)
37
38
39 def CopyProjectFiles(project_source, out_dir):
40   """cp xwalk/build/android/xwalkcore_library_template/<file>
41         out/Release/xwalk_core_library/<file>
42   """
43
44   print 'Copying library project files...'
45   template_dir = os.path.join(project_source, 'xwalk', 'build', 'android',
46                               'xwalkcore_library_template')
47   files_to_copy = [
48       # AndroidManifest.xml from template.
49       'AndroidManifest.xml',
50       # Eclipse project properties from template.
51       'project.properties',
52       # Ant build file.
53       'build.xml',
54       # Ant properties file.
55       'ant.properties',
56   ]
57   for f in files_to_copy:
58     source_file = os.path.join(template_dir, f)
59     target_file = os.path.join(out_dir, LIBRARY_PROJECT_NAME, f)
60
61     shutil.copy2(source_file, target_file)
62
63
64 def CopyJavaSources(project_source, out_dir):
65   """cp <path>/java/src/<package>
66         out/Release/xwalk_core_library/src/<package>
67   """
68
69   print 'Copying Java sources...'
70   target_source_dir = os.path.join(
71       out_dir, LIBRARY_PROJECT_NAME, 'src')
72   if not os.path.exists(target_source_dir):
73     os.makedirs(target_source_dir)
74
75   # FIXME(wang16): There is an assumption here the package names listed
76   # here are all beginned with "org". If the assumption is broken in
77   # future, the logic needs to be adjusted accordingly.
78   java_srcs_to_copy = [
79       # Chromium java sources.
80       'base/android/java/src/org/chromium/base',
81       'content/public/android/java/src/org/chromium/content',
82       'content/public/android/java/src/org/chromium/content_public',
83       'media/base/android/java/src/org/chromium/media',
84       'net/android/java/src/org/chromium/net',
85       'ui/android/java/src/org/chromium/ui',
86       'components/navigation_interception/android/java/'
87           'src/org/chromium/components/navigation_interception',
88       'components/web_contents_delegate_android/android/java/'
89           'src/org/chromium/components/web_contents_delegate_android',
90
91       # R.javas
92       'content/public/android/java/resource_map/org/chromium/content/R.java',
93       'ui/android/java/resource_map/org/chromium/ui/R.java',
94
95       # XWalk java sources.
96       'xwalk/runtime/android/core/src/org/xwalk/core',
97       'xwalk/extensions/android/java/src/org/xwalk/core/extensions',
98   ]
99
100   for source in java_srcs_to_copy:
101     # find the src/org in the path
102     slash_org_pos = source.find(r'/org/')
103     if slash_org_pos < 0:
104       raise Exception('Invalid java source path: %s' % source)
105     source_path = os.path.join(project_source, source)
106     package_path = source[slash_org_pos+1:]
107     target_path = os.path.join(target_source_dir, package_path)
108     if os.path.isfile(source_path):
109       if not os.path.isdir(os.path.dirname(target_path)):
110         os.makedirs(os.path.dirname(target_path))
111       shutil.copyfile(source_path, target_path)
112     else:
113       shutil.copytree(source_path, target_path)
114
115
116 def CopyGeneratedSources(out_dir):
117   """cp out/Release/gen/templates/<path>
118         out/Release/xwalk_core_library/src/<path>
119      cp out/Release/xwalk_core_shell_apk/
120             native_libraries_java/NativeLibraries.java
121         out/Release/xwalk_core_library/src/org/
122             chromium/base/library_loader/NativeLibraries.java
123   """
124
125   print 'Copying generated source files...'
126   generated_srcs_to_copy = [
127       'org/chromium/base/ApplicationState.java',
128       'org/chromium/base/MemoryPressureLevelList.java',
129       'org/chromium/base/library_loader/NativeLibraries.java',
130       'org/chromium/content/browser/GestureEventType.java',
131       'org/chromium/content/browser/input/PopupItemType.java',
132       'org/chromium/content/browser/PageTransitionTypes.java',
133       'org/chromium/content/browser/SpeechRecognitionError.java',
134       'org/chromium/content/common/ResultCodes.java',
135       'org/chromium/content/common/ScreenOrientationValues.java',
136       'org/chromium/content/common/TopControlsState.java',
137       'org/chromium/media/ImageFormat.java',
138       'org/chromium/net/CertificateMimeType.java',
139       'org/chromium/net/CertVerifyStatusAndroid.java',
140       'org/chromium/net/NetError.java',
141       'org/chromium/net/PrivateKeyType.java',
142       'org/chromium/ui/gfx/BitmapFormat.java',
143       'org/chromium/ui/WindowOpenDisposition.java'
144   ]
145
146   for source in generated_srcs_to_copy:
147     source_file = os.path.join(out_dir, 'gen', 'templates', source)
148     target_file = os.path.join(
149         out_dir, LIBRARY_PROJECT_NAME, 'src', source)
150     shutil.copyfile(source_file, target_file)
151
152   source_file = os.path.join(out_dir, XWALK_CORE_SHELL_APK,
153                              'native_libraries_java',
154                              'NativeLibraries.java')
155   target_file = os.path.join(out_dir, LIBRARY_PROJECT_NAME, 'src', 'org',
156                              'chromium', 'base', 'library_loader',
157                              'NativeLibraries.java')
158   shutil.copyfile(source_file, target_file)
159
160 def CopyJSBindingFiles(project_source, out_dir):
161   print 'Copying js binding files...'
162   jsapi_dir = os.path.join(out_dir,
163                            LIBRARY_PROJECT_NAME,
164                            'res',
165                            'raw')
166   if not os.path.exists(jsapi_dir):
167     os.makedirs(jsapi_dir)
168
169   jsfiles_to_copy = [
170       'xwalk/experimental/launch_screen/launch_screen_api.js',
171       'xwalk/experimental/presentation/presentation_api.js',
172       'xwalk/runtime/extension/screen_orientation_api.js',
173       'xwalk/sysapps/device_capabilities/device_capabilities_api.js'
174   ]
175
176   # Copy JS binding file to assets/jsapi folder.
177   for jsfile in jsfiles_to_copy:
178     source_file = os.path.join(project_source, jsfile)
179     target_file = os.path.join(jsapi_dir, os.path.basename(source_file))
180     shutil.copyfile(source_file, target_file)
181
182
183 def CopyBinaries(out_dir):
184   """cp out/Release/<pak> out/Release/xwalk_core_library/res/raw/<pak>
185      cp out/Release/lib.java/<lib> out/Release/xwalk_core_library/libs/<lib>
186      cp out/Release/xwalk_core_shell_apk/libs/*
187         out/Release/xwalk_core_library/libs
188   """
189
190   print 'Copying binaries...'
191   # Copy assets.
192   res_raw_dir = os.path.join(
193       out_dir, LIBRARY_PROJECT_NAME, 'res', 'raw')
194   res_value_dir = os.path.join(
195       out_dir, LIBRARY_PROJECT_NAME, 'res', 'values')
196   if not os.path.exists(res_raw_dir):
197     os.mkdir(res_raw_dir)
198   if not os.path.exists(res_value_dir):
199     os.mkdir(res_value_dir)
200
201   paks_to_copy = [
202       'icudtl.dat',
203       'xwalk.pak',
204   ]
205
206   pak_list_xml = Document()
207   resources_node = pak_list_xml.createElement('resources')
208   string_array_node = pak_list_xml.createElement('string-array')
209   string_array_node.setAttribute('name', 'xwalk_resources_list')
210   pak_list_xml.appendChild(resources_node)
211   resources_node.appendChild(string_array_node)
212   for pak in paks_to_copy:
213     source_file = os.path.join(out_dir, pak)
214     target_file = os.path.join(res_raw_dir, pak)
215     shutil.copyfile(source_file, target_file)
216     item_node = pak_list_xml.createElement('item')
217     item_node.appendChild(pak_list_xml.createTextNode(pak))
218     string_array_node.appendChild(item_node)
219   pak_list_file = open(os.path.join(res_value_dir,
220                                     'xwalk_resources_list.xml'), 'w')
221   pak_list_xml.writexml(pak_list_file, newl='\n', encoding='utf-8')
222   pak_list_file.close()
223
224   # Copy jar files to libs.
225   libs_dir = os.path.join(out_dir, LIBRARY_PROJECT_NAME, 'libs')
226   if not os.path.exists(libs_dir):
227     os.mkdir(libs_dir)
228
229   libs_to_copy = [
230       'eyesfree_java.jar',
231       'guava_javalib.jar',
232       'jsr_305_javalib.jar',
233   ]
234
235   for lib in libs_to_copy:
236     source_file = os.path.join(out_dir, 'lib.java', lib)
237     target_file = os.path.join(libs_dir, lib)
238     shutil.copyfile(source_file, target_file)
239
240   # Copy native libraries.
241   source_dir = os.path.join(out_dir, XWALK_CORE_SHELL_APK, 'libs')
242   target_dir = libs_dir
243   distutils.dir_util.copy_tree(source_dir, target_dir)
244
245
246 def CopyDirAndPrefixDuplicates(input_dir, output_dir, prefix):
247   """ Copy the files into the output directory. If one file in input_dir folder
248   doesn't exist, copy it directly. If a file exists, copy it and rename the
249   file so that the resources won't be overrided. So all of them could be
250   packaged into the xwalk core library.
251   """
252   for root, _, files in os.walk(input_dir):
253     for f in files:
254       src_file = os.path.join(root, f)
255       relative_path = os.path.relpath(src_file, input_dir)
256       target_file = os.path.join(output_dir, relative_path)
257       target_dir_name = os.path.dirname(target_file)
258       if not os.path.exists(target_dir_name):
259         os.makedirs(target_dir_name)
260       # If the file exists, copy it and rename it with another name to
261       # avoid overwriting the existing one.
262       if os.path.exists(target_file):
263         target_base_name = os.path.basename(target_file)
264         target_base_name = prefix + '_' + target_base_name
265         target_file = os.path.join(target_dir_name, target_base_name)
266       shutil.copyfile(src_file, target_file)
267
268
269 def CopyResources(project_source, out_dir):
270   print 'Copying resources...'
271   res_dir = os.path.join(out_dir, LIBRARY_PROJECT_NAME, 'res')
272   if os.path.exists(res_dir):
273     shutil.rmtree(res_dir)
274
275   # All resources should be in specific folders in res_directory.
276   # Since there might be some resource files with same names from
277   # different folders like ui_java, content_java and others,
278   # it's necessary to rename some files to avoid overridding.
279   res_to_copy = [
280       # (package, prefix) turple.
281       ('ui/android/java/res', 'ui'),
282       ('content/public/android/java/res', 'content'),
283       ('xwalk/runtime/android/java/res', 'xwalk_core'),
284   ]
285
286   # For each res, there are two generated res folder in out directory,
287   # they are res_grit and res_v14_compatibility.
288   for res, prefix in res_to_copy:
289     res_path_src = os.path.join(project_source, res)
290     res_path_grit = os.path.join(out_dir,
291         'gen', '%s_java' % prefix, 'res_grit')
292     res_path_v14 = os.path.join(out_dir,
293         'gen', '%s_java' % prefix, 'res_v14_compatibility')
294
295     for res_path in [res_path_src, res_path_grit, res_path_v14]:
296       CopyDirAndPrefixDuplicates(res_path, res_dir, prefix)
297
298
299 def PostCopyLibraryProject(out_dir):
300   print 'Post Copy Library Project...'
301   aidls_to_remove = [
302       'org/chromium/content/common/common.aidl',
303       'org/chromium/net/IRemoteAndroidKeyStoreInterface.aidl',
304   ]
305   for aidl in aidls_to_remove:
306     aidl_file = os.path.join(out_dir, LIBRARY_PROJECT_NAME, 'src', aidl)
307     if os.path.exists(aidl_file):
308       os.remove(aidl_file)
309
310
311 def main(argv):
312   print 'Generating XWalkCore Library Project...'
313   option_parser = optparse.OptionParser()
314   AddGeneratorOptions(option_parser)
315   options, _ = option_parser.parse_args(argv)
316
317   if not os.path.exists(options.source):
318     print 'Source project does not exist, please provide correct directory.'
319     sys.exit(1)
320   out_dir = options.target
321
322   # Clean directory for project first.
323   CleanLibraryProject(out_dir)
324
325   out_project_dir = os.path.join(out_dir, LIBRARY_PROJECT_NAME)
326   if not os.path.exists(out_project_dir):
327     os.mkdir(out_project_dir)
328
329   # Copy Eclipse project files of library project.
330   CopyProjectFiles(options.source, out_dir)
331   # Copy Java sources of chromium and xwalk.
332   CopyJavaSources(options.source, out_dir)
333   CopyGeneratedSources(out_dir)
334   # Copy binaries and resuorces.
335   CopyResources(options.source, out_dir)
336   CopyBinaries(out_dir)
337   # Copy JS API binding files.
338   CopyJSBindingFiles(options.source, out_dir)
339   # Post copy library project.
340   PostCopyLibraryProject(out_dir)
341   # Remove unused files.
342   mode = os.path.basename(os.path.normpath(out_dir))
343   RemoveUnusedFilesInReleaseMode(mode,
344       os.path.join(out_dir, LIBRARY_PROJECT_NAME, 'libs'))
345   print 'Your Android library project has been created at %s' % (
346       out_project_dir)
347
348 if __name__ == '__main__':
349   sys.exit(main(sys.argv))