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