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/sysapps/device_capabilities/device_capabilities_api.js'
80 # Copy JS binding file to assets/jsapi folder.
81 for jsfile in jsfiles_to_copy:
82 source_file = os.path.join(project_source, jsfile)
83 target_file = os.path.join(jsapi_dir, os.path.basename(source_file))
84 shutil.copyfile(source_file, target_file)
87 def CopyBinaries(out_dir):
88 """cp out/Release/<pak> out/Release/xwalk_core_library/res/raw/<pak>
89 cp out/Release/lib.java/<lib> out/Release/xwalk_core_library/libs/<lib>
90 cp out/Release/xwalk_core_shell_apk/libs/*
91 out/Release/xwalk_core_library/libs
94 print 'Copying binaries...'
96 res_raw_dir = os.path.join(
97 out_dir, LIBRARY_PROJECT_NAME, 'res', 'raw')
98 res_value_dir = os.path.join(
99 out_dir, LIBRARY_PROJECT_NAME, 'res', 'values')
100 if not os.path.exists(res_raw_dir):
101 os.mkdir(res_raw_dir)
102 if not os.path.exists(res_value_dir):
103 os.mkdir(res_value_dir)
110 pak_list_xml = Document()
111 resources_node = pak_list_xml.createElement('resources')
112 string_array_node = pak_list_xml.createElement('string-array')
113 string_array_node.setAttribute('name', 'xwalk_resources_list')
114 pak_list_xml.appendChild(resources_node)
115 resources_node.appendChild(string_array_node)
116 for pak in paks_to_copy:
117 source_file = os.path.join(out_dir, pak)
118 target_file = os.path.join(res_raw_dir, pak)
119 shutil.copyfile(source_file, target_file)
120 item_node = pak_list_xml.createElement('item')
121 item_node.appendChild(pak_list_xml.createTextNode(pak))
122 string_array_node.appendChild(item_node)
123 pak_list_file = open(os.path.join(res_value_dir,
124 'xwalk_resources_list.xml'), 'w')
125 pak_list_xml.writexml(pak_list_file, newl='\n', encoding='utf-8')
126 pak_list_file.close()
128 # Copy jar files to libs.
129 libs_dir = os.path.join(out_dir, LIBRARY_PROJECT_NAME, 'libs')
130 if not os.path.exists(libs_dir):
134 'xwalk_core_library_java.jar',
137 for lib in libs_to_copy:
138 source_file = os.path.join(out_dir, 'lib.java', lib)
139 target_file = os.path.join(libs_dir, lib)
140 shutil.copyfile(source_file, target_file)
142 # Copy native libraries.
143 source_dir = os.path.join(out_dir, XWALK_CORE_SHELL_APK, 'libs')
144 target_dir = libs_dir
145 distutils.dir_util.copy_tree(source_dir, target_dir)
148 def CopyDirAndPrefixDuplicates(input_dir, output_dir, prefix):
149 """ Copy the files into the output directory. If one file in input_dir folder
150 doesn't exist, copy it directly. If a file exists, copy it and rename the
151 file so that the resources won't be overrided. So all of them could be
152 packaged into the xwalk core library.
154 for root, _, files in os.walk(input_dir):
156 src_file = os.path.join(root, f)
157 relative_path = os.path.relpath(src_file, input_dir)
158 target_file = os.path.join(output_dir, relative_path)
159 target_dir_name = os.path.dirname(target_file)
160 if not os.path.exists(target_dir_name):
161 os.makedirs(target_dir_name)
162 # If the file exists, copy it and rename it with another name to
163 # avoid overwriting the existing one.
164 if os.path.exists(target_file):
165 target_base_name = os.path.basename(target_file)
166 target_base_name = prefix + '_' + target_base_name
167 target_file = os.path.join(target_dir_name, target_base_name)
168 shutil.copyfile(src_file, target_file)
171 def MoveImagesToNonMdpiFolders(res_root):
172 """Move images from drawable-*-mdpi-* folders to drawable-* folders.
174 Why? http://crbug.com/289843
176 Copied from build/android/gyp/package_resources.py.
178 for src_dir_name in os.listdir(res_root):
179 src_components = src_dir_name.split('-')
180 if src_components[0] != 'drawable' or 'mdpi' not in src_components:
182 src_dir = os.path.join(res_root, src_dir_name)
183 if not os.path.isdir(src_dir):
185 dst_components = [c for c in src_components if c != 'mdpi']
186 assert dst_components != src_components
187 dst_dir_name = '-'.join(dst_components)
188 dst_dir = os.path.join(res_root, dst_dir_name)
189 if not os.path.isdir(dst_dir):
191 for src_file_name in os.listdir(src_dir):
192 if not src_file_name.endswith('.png'):
194 src_file = os.path.join(src_dir, src_file_name)
195 dst_file = os.path.join(dst_dir, src_file_name)
196 assert not os.path.lexists(dst_file)
197 shutil.move(src_file, dst_file)
200 def CopyResources(out_dir):
201 print 'Copying resources...'
202 res_dir = os.path.join(out_dir, LIBRARY_PROJECT_NAME, 'res')
203 temp_dir = os.path.join(out_dir, LIBRARY_PROJECT_NAME, 'temp')
204 if os.path.exists(res_dir):
205 shutil.rmtree(res_dir)
206 if os.path.exists(temp_dir):
207 shutil.rmtree(temp_dir)
209 # All resources should be in specific folders in res_directory.
210 # Since there might be some resource files with same names from
211 # different folders like ui_java, content_java and others,
212 # it's necessary to rename some files to avoid overridding.
216 'content_strings_grd.zip',
218 'ui_strings_grd.zip',
219 'xwalk_core_internal_java.zip',
220 'xwalk_core_strings.zip'
223 for res_zip in res_to_copy:
224 zip_file = os.path.join(out_dir, 'res.java', res_zip)
225 zip_name = os.path.splitext(res_zip)[0]
226 if not os.path.isfile(zip_file):
227 raise Exception('Resource zip not found: ' + zip_file)
228 subdir = os.path.join(temp_dir, zip_name)
229 if os.path.isdir(subdir):
230 raise Exception('Resource zip name conflict: ' + zip_name)
232 with zipfile.ZipFile(zip_file) as z:
233 z.extractall(path=subdir)
234 CopyDirAndPrefixDuplicates(subdir, res_dir, zip_name)
235 MoveImagesToNonMdpiFolders(res_dir)
237 if os.path.isdir(temp_dir):
238 shutil.rmtree(temp_dir)
241 def PostCopyLibraryProject(out_dir):
242 print 'Post Copy Library Project...'
244 'org/chromium/content/common/common.aidl',
245 'org/chromium/net/IRemoteAndroidKeyStoreInterface.aidl',
247 for aidl in aidls_to_remove:
248 aidl_file = os.path.join(out_dir, LIBRARY_PROJECT_NAME, 'src', aidl)
249 if os.path.exists(aidl_file):
254 print 'Generating XWalkCore Library Project...'
255 option_parser = optparse.OptionParser()
256 AddGeneratorOptions(option_parser)
257 options, _ = option_parser.parse_args(argv)
259 if not os.path.exists(options.source):
260 print 'Source project does not exist, please provide correct directory.'
262 out_dir = options.target
264 # Clean directory for project first.
265 CleanLibraryProject(out_dir)
267 out_project_dir = os.path.join(out_dir, LIBRARY_PROJECT_NAME)
268 if not os.path.exists(out_project_dir):
269 os.mkdir(out_project_dir)
271 # Copy Eclipse project files of library project.
272 CopyProjectFiles(options.source, out_dir)
273 # Copy binaries and resuorces.
274 CopyResources(out_dir)
275 CopyBinaries(out_dir)
276 # Copy JS API binding files.
277 CopyJSBindingFiles(options.source, out_dir)
278 # Post copy library project.
279 PostCopyLibraryProject(out_dir)
280 # Remove unused files.
281 mode = os.path.basename(os.path.normpath(out_dir))
282 RemoveUnusedFilesInReleaseMode(mode,
283 os.path.join(out_dir, LIBRARY_PROJECT_NAME, 'libs'))
284 # Create empty src directory
285 src_dir = os.path.join(out_project_dir, 'src')
286 if not os.path.isdir(src_dir):
288 readme = os.path.join(src_dir, 'README.md')
289 open(readme, 'w').write(
290 "# Source folder for xwalk_core_library\n"
291 "## Why it's empty\n"
292 "xwalk_core_library doesn't contain java sources.\n"
293 "## Why put me here\n"
294 "To make archives keep the folder, "
295 "the src directory is needed to build an apk by ant.")
296 print 'Your Android library project has been created at %s' % (
299 if __name__ == '__main__':
300 sys.exit(main(sys.argv))