Upstream version 11.40.277.0
[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 import zipfile
14 from common_function import RemoveUnusedFilesInReleaseMode
15 from xml.dom.minidom import Document
16
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   option_parser.add_option('--src-package', action='store_true',
27                            default=False,
28                            help='Use java sources instead of java libs.')
29
30
31 def CleanLibraryProject(out_project_dir):
32   if os.path.exists(out_project_dir):
33     for item in os.listdir(out_project_dir):
34       sub_path = os.path.join(out_project_dir, item)
35       if os.path.isdir(sub_path):
36         shutil.rmtree(sub_path)
37       elif os.path.isfile(sub_path):
38         os.remove(sub_path)
39
40
41 def CopyProjectFiles(project_source, out_project_dir):
42   """cp xwalk/build/android/xwalkcore_library_template/<file>
43         out/Release/xwalk_core_library/<file>
44   """
45
46   print 'Copying library project files...'
47   template_dir = os.path.join(project_source, 'xwalk', 'build', 'android',
48                               'xwalkcore_library_template')
49   files_to_copy = [
50       # AndroidManifest.xml from template.
51       'AndroidManifest.xml',
52       # Eclipse project properties from template.
53       'project.properties',
54       # Ant build file.
55       'build.xml',
56       # Ant properties file.
57       'ant.properties',
58   ]
59   for f in files_to_copy:
60     source_file = os.path.join(template_dir, f)
61     target_file = os.path.join(out_project_dir, f)
62
63     shutil.copy2(source_file, target_file)
64
65
66 def CopyJSBindingFiles(project_source, out_project_dir):
67   print 'Copying js binding files...'
68   jsapi_dir = os.path.join(out_project_dir, 'res', 'raw')
69   if not os.path.exists(jsapi_dir):
70     os.makedirs(jsapi_dir)
71
72   jsfiles_to_copy = [
73       'xwalk/experimental/launch_screen/launch_screen_api.js',
74       'xwalk/experimental/presentation/presentation_api.js',
75       'xwalk/runtime/android/core_internal/src/org/xwalk/core/'
76       + 'internal/extension/api/contacts/contacts_api.js',
77       'xwalk/runtime/android/core_internal/src/org/xwalk/core/'
78       + 'internal/extension/api/device_capabilities/device_capabilities_api.js',
79       'xwalk/runtime/android/core_internal/src/org/xwalk/core/'
80       + 'internal/extension/api/messaging/messaging_api.js'
81   ]
82
83   # Copy JS binding file to assets/jsapi folder.
84   for jsfile in jsfiles_to_copy:
85     source_file = os.path.join(project_source, jsfile)
86     target_file = os.path.join(jsapi_dir, os.path.basename(source_file))
87     shutil.copyfile(source_file, target_file)
88
89
90 def CopyBinaries(out_dir, out_project_dir, src_package):
91   """cp out/Release/<pak> out/Release/xwalk_core_library/res/raw/<pak>
92      cp out/Release/lib.java/<lib> out/Release/xwalk_core_library/libs/<lib>
93      cp out/Release/xwalk_core_shell_apk/libs/*
94         out/Release/xwalk_core_library/libs
95   """
96
97   print 'Copying binaries...'
98   # Copy assets.
99   res_raw_dir = os.path.join(out_project_dir, 'res', 'raw')
100   res_value_dir = os.path.join(out_project_dir, 'res', 'values')
101   if not os.path.exists(res_raw_dir):
102     os.mkdir(res_raw_dir)
103   if not os.path.exists(res_value_dir):
104     os.mkdir(res_value_dir)
105
106   paks_to_copy = [
107       'icudtl.dat',
108       'xwalk.pak',
109   ]
110
111   pak_list_xml = Document()
112   resources_node = pak_list_xml.createElement('resources')
113   string_array_node = pak_list_xml.createElement('string-array')
114   string_array_node.setAttribute('name', 'xwalk_resources_list')
115   pak_list_xml.appendChild(resources_node)
116   resources_node.appendChild(string_array_node)
117   for pak in paks_to_copy:
118     source_file = os.path.join(out_dir, pak)
119     target_file = os.path.join(res_raw_dir, pak)
120     shutil.copyfile(source_file, target_file)
121     item_node = pak_list_xml.createElement('item')
122     item_node.appendChild(pak_list_xml.createTextNode(pak))
123     string_array_node.appendChild(item_node)
124   pak_list_file = open(os.path.join(res_value_dir,
125                                     'xwalk_resources_list.xml'), 'w')
126   pak_list_xml.writexml(pak_list_file, newl='\n', encoding='utf-8')
127   pak_list_file.close()
128
129   libs_dir = os.path.join(out_project_dir, 'libs')
130   if not os.path.exists(libs_dir):
131     os.mkdir(libs_dir)
132
133   # Copy jar files to libs.
134   if src_package:
135     libs_to_copy = [
136         'eyesfree_java.jar',
137         'jsr_305_javalib.jar',
138     ]
139   else:
140     libs_to_copy = [
141         'xwalk_core_library_java_app_part.jar',
142         'xwalk_core_library_java_library_part.jar',
143     ]
144
145   for lib in libs_to_copy:
146     source_file = os.path.join(out_dir, 'lib.java', lib)
147     target_file = os.path.join(libs_dir, lib)
148     shutil.copyfile(source_file, target_file)
149
150   # Copy native libraries.
151   source_dir = os.path.join(out_dir, XWALK_CORE_SHELL_APK, 'libs')
152   target_dir = libs_dir
153   distutils.dir_util.copy_tree(source_dir, target_dir)
154
155
156 def CopyDirAndPrefixDuplicates(input_dir, output_dir, prefix):
157   """ Copy the files into the output directory. If one file in input_dir folder
158   doesn't exist, copy it directly. If a file exists, copy it and rename the
159   file so that the resources won't be overrided. So all of them could be
160   packaged into the xwalk core library.
161   """
162   for root, _, files in os.walk(input_dir):
163     for f in files:
164       src_file = os.path.join(root, f)
165       relative_path = os.path.relpath(src_file, input_dir)
166       target_file = os.path.join(output_dir, relative_path)
167       target_dir_name = os.path.dirname(target_file)
168       if not os.path.exists(target_dir_name):
169         os.makedirs(target_dir_name)
170       # If the file exists, copy it and rename it with another name to
171       # avoid overwriting the existing one.
172       if os.path.exists(target_file):
173         target_base_name = os.path.basename(target_file)
174         target_base_name = prefix + '_' + target_base_name
175         target_file = os.path.join(target_dir_name, target_base_name)
176       shutil.copyfile(src_file, target_file)
177
178
179 def MoveImagesToNonMdpiFolders(res_root):
180   """Move images from drawable-*-mdpi-* folders to drawable-* folders.
181
182   Why? http://crbug.com/289843
183
184   Copied from build/android/gyp/package_resources.py.
185   """
186   for src_dir_name in os.listdir(res_root):
187     src_components = src_dir_name.split('-')
188     if src_components[0] != 'drawable' or 'mdpi' not in src_components:
189       continue
190     src_dir = os.path.join(res_root, src_dir_name)
191     if not os.path.isdir(src_dir):
192       continue
193     dst_components = [c for c in src_components if c != 'mdpi']
194     assert dst_components != src_components
195     dst_dir_name = '-'.join(dst_components)
196     dst_dir = os.path.join(res_root, dst_dir_name)
197     if not os.path.isdir(dst_dir):
198       os.makedirs(dst_dir)
199     for src_file_name in os.listdir(src_dir):
200       if not src_file_name.endswith('.png'):
201         continue
202       src_file = os.path.join(src_dir, src_file_name)
203       dst_file = os.path.join(dst_dir, src_file_name)
204       assert not os.path.lexists(dst_file)
205       shutil.move(src_file, dst_file)
206
207
208 def ReplaceCrunchedImage(project_source, filename, filepath):
209   """Replace crunched images with source images.
210   """
211   search_dir = [
212       'content/public/android/java/res',
213       'ui/android/java/res'
214   ]
215
216   pathname = os.path.basename(filepath)
217   #replace crunched 9-patch image resources.
218   for search in search_dir:
219     absdir = os.path.join(project_source, search)
220     for dirname, _, files in os.walk(absdir):
221       if filename in files:
222         relativedir = os.path.basename(dirname)
223         if (pathname == 'drawable' and relativedir == 'drawable-mdpi') or \
224             relativedir == pathname:
225           source_file = os.path.abspath(os.path.join(dirname, filename))
226           target_file = os.path.join(filepath, filename)
227           shutil.copyfile(source_file, target_file)
228           return
229
230
231 def CopyResources(project_source, out_dir, out_project_dir):
232   print 'Copying resources...'
233   res_dir = os.path.join(out_project_dir, 'res')
234   temp_dir = os.path.join(out_project_dir, 'temp')
235   if os.path.exists(res_dir):
236     shutil.rmtree(res_dir)
237   if os.path.exists(temp_dir):
238     shutil.rmtree(temp_dir)
239
240   # All resources should be in specific folders in res_directory.
241   # Since there might be some resource files with same names from
242   # different folders like ui_java, content_java and others,
243   # it's necessary to rename some files to avoid overridding.
244   res_to_copy = [
245       # zip file list
246       'content_java.zip',
247       'content_strings_grd.zip',
248       'ui_java.zip',
249       'ui_strings_grd.zip',
250       'xwalk_core_internal_java.zip',
251       'xwalk_core_strings.zip'
252   ]
253
254   for res_zip in res_to_copy:
255     zip_file = os.path.join(out_dir, 'res.java', res_zip)
256     zip_name = os.path.splitext(res_zip)[0]
257     if not os.path.isfile(zip_file):
258       raise Exception('Resource zip not found: ' + zip_file)
259     subdir = os.path.join(temp_dir, zip_name)
260     if os.path.isdir(subdir):
261       raise Exception('Resource zip name conflict: ' + zip_name)
262     os.makedirs(subdir)
263     with zipfile.ZipFile(zip_file) as z:
264       z.extractall(path=subdir)
265     CopyDirAndPrefixDuplicates(subdir, res_dir, zip_name)
266     MoveImagesToNonMdpiFolders(res_dir)
267
268   if os.path.isdir(temp_dir):
269     shutil.rmtree(temp_dir)
270
271   #search 9-patch, then replace it with uncrunch image.
272   for dirname, _, files in os.walk(res_dir):
273     for filename in files:
274       if filename.endswith('.9.png'):
275         ReplaceCrunchedImage(project_source, filename, dirname)
276
277
278 def main(argv):
279   print 'Generating XWalkCore Library Project...'
280   option_parser = optparse.OptionParser()
281   AddGeneratorOptions(option_parser)
282   options, _ = option_parser.parse_args(argv)
283
284   if not os.path.exists(options.source):
285     print 'Source project does not exist, please provide correct directory.'
286     sys.exit(1)
287   out_dir = options.target
288   if options.src_package:
289     out_project_dir = os.path.join(out_dir, 'xwalk_core_library_src')
290   else:
291     out_project_dir = os.path.join(out_dir, 'xwalk_core_library')
292
293   # Clean directory for project first.
294   CleanLibraryProject(out_project_dir)
295
296   if not os.path.exists(out_project_dir):
297     os.mkdir(out_project_dir)
298
299   # Copy Eclipse project files of library project.
300   CopyProjectFiles(options.source, out_project_dir)
301   # Copy binaries and resuorces.
302   CopyResources(options.source, out_dir, out_project_dir)
303   CopyBinaries(out_dir, out_project_dir, options.src_package)
304   # Copy JS API binding files.
305   CopyJSBindingFiles(options.source, out_project_dir)
306   # Remove unused files.
307   mode = os.path.basename(os.path.normpath(out_dir))
308   RemoveUnusedFilesInReleaseMode(mode,
309       os.path.join(out_project_dir, 'libs'))
310   # Create empty src directory
311   src_dir = os.path.join(out_project_dir, 'src')
312   if not os.path.isdir(src_dir):
313     os.mkdir(src_dir)
314   readme = os.path.join(src_dir, 'README.md')
315   open(readme, 'w').write(
316       "# Source folder for xwalk_core_library\n"
317       "## Why it's empty\n"
318       "xwalk_core_library doesn't contain java sources.\n"
319       "## Why put me here\n"
320       "To make archives keep the folder, "
321       "the src directory is needed to build an apk by ant.")
322   print 'Your Android library project has been created at %s' % (
323       out_project_dir)
324
325 if __name__ == '__main__':
326   sys.exit(main(sys.argv))