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/device_capabilities/device_capabilities_api.js'
81 # Copy JS binding file to assets/jsapi folder.
82 for jsfile in jsfiles_to_copy:
83 source_file = os.path.join(project_source, jsfile)
84 target_file = os.path.join(jsapi_dir, os.path.basename(source_file))
85 shutil.copyfile(source_file, target_file)
88 def CopyBinaries(out_dir):
89 """cp out/Release/<pak> out/Release/xwalk_core_library/res/raw/<pak>
90 cp out/Release/lib.java/<lib> out/Release/xwalk_core_library/libs/<lib>
91 cp out/Release/xwalk_core_shell_apk/libs/*
92 out/Release/xwalk_core_library/libs
95 print 'Copying binaries...'
97 res_raw_dir = os.path.join(
98 out_dir, LIBRARY_PROJECT_NAME, 'res', 'raw')
99 res_value_dir = os.path.join(
100 out_dir, LIBRARY_PROJECT_NAME, '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)
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()
129 # Copy jar files to libs.
130 libs_dir = os.path.join(out_dir, LIBRARY_PROJECT_NAME, 'libs')
131 if not os.path.exists(libs_dir):
135 'xwalk_core_library_java.jar',
138 for lib in libs_to_copy:
139 source_file = os.path.join(out_dir, 'lib.java', lib)
140 target_file = os.path.join(libs_dir, lib)
141 shutil.copyfile(source_file, target_file)
143 # Copy native libraries.
144 source_dir = os.path.join(out_dir, XWALK_CORE_SHELL_APK, 'libs')
145 target_dir = libs_dir
146 distutils.dir_util.copy_tree(source_dir, target_dir)
149 def CopyDirAndPrefixDuplicates(input_dir, output_dir, prefix):
150 """ Copy the files into the output directory. If one file in input_dir folder
151 doesn't exist, copy it directly. If a file exists, copy it and rename the
152 file so that the resources won't be overrided. So all of them could be
153 packaged into the xwalk core library.
155 for root, _, files in os.walk(input_dir):
157 src_file = os.path.join(root, f)
158 relative_path = os.path.relpath(src_file, input_dir)
159 target_file = os.path.join(output_dir, relative_path)
160 target_dir_name = os.path.dirname(target_file)
161 if not os.path.exists(target_dir_name):
162 os.makedirs(target_dir_name)
163 # If the file exists, copy it and rename it with another name to
164 # avoid overwriting the existing one.
165 if os.path.exists(target_file):
166 target_base_name = os.path.basename(target_file)
167 target_base_name = prefix + '_' + target_base_name
168 target_file = os.path.join(target_dir_name, target_base_name)
169 shutil.copyfile(src_file, target_file)
172 def MoveImagesToNonMdpiFolders(res_root):
173 """Move images from drawable-*-mdpi-* folders to drawable-* folders.
175 Why? http://crbug.com/289843
177 Copied from build/android/gyp/package_resources.py.
179 for src_dir_name in os.listdir(res_root):
180 src_components = src_dir_name.split('-')
181 if src_components[0] != 'drawable' or 'mdpi' not in src_components:
183 src_dir = os.path.join(res_root, src_dir_name)
184 if not os.path.isdir(src_dir):
186 dst_components = [c for c in src_components if c != 'mdpi']
187 assert dst_components != src_components
188 dst_dir_name = '-'.join(dst_components)
189 dst_dir = os.path.join(res_root, dst_dir_name)
190 if not os.path.isdir(dst_dir):
192 for src_file_name in os.listdir(src_dir):
193 if not src_file_name.endswith('.png'):
195 src_file = os.path.join(src_dir, src_file_name)
196 dst_file = os.path.join(dst_dir, src_file_name)
197 assert not os.path.lexists(dst_file)
198 shutil.move(src_file, dst_file)
201 def CopyResources(out_dir):
202 print 'Copying resources...'
203 res_dir = os.path.join(out_dir, LIBRARY_PROJECT_NAME, 'res')
204 temp_dir = os.path.join(out_dir, LIBRARY_PROJECT_NAME, 'temp')
205 if os.path.exists(res_dir):
206 shutil.rmtree(res_dir)
207 if os.path.exists(temp_dir):
208 shutil.rmtree(temp_dir)
210 # All resources should be in specific folders in res_directory.
211 # Since there might be some resource files with same names from
212 # different folders like ui_java, content_java and others,
213 # it's necessary to rename some files to avoid overridding.
217 'content_strings_grd.zip',
219 'ui_strings_grd.zip',
220 'xwalk_core_internal_java.zip',
221 'xwalk_core_strings.zip'
224 for res_zip in res_to_copy:
225 zip_file = os.path.join(out_dir, 'res.java', res_zip)
226 zip_name = os.path.splitext(res_zip)[0]
227 if not os.path.isfile(zip_file):
228 raise Exception('Resource zip not found: ' + zip_file)
229 subdir = os.path.join(temp_dir, zip_name)
230 if os.path.isdir(subdir):
231 raise Exception('Resource zip name conflict: ' + zip_name)
233 with zipfile.ZipFile(zip_file) as z:
234 z.extractall(path=subdir)
235 CopyDirAndPrefixDuplicates(subdir, res_dir, zip_name)
236 MoveImagesToNonMdpiFolders(res_dir)
238 if os.path.isdir(temp_dir):
239 shutil.rmtree(temp_dir)
242 def PostCopyLibraryProject(out_dir):
243 print 'Post Copy Library Project...'
245 'org/chromium/content/common/common.aidl',
246 'org/chromium/net/IRemoteAndroidKeyStoreInterface.aidl',
248 for aidl in aidls_to_remove:
249 aidl_file = os.path.join(out_dir, LIBRARY_PROJECT_NAME, 'src', aidl)
250 if os.path.exists(aidl_file):
255 print 'Generating XWalkCore Library Project...'
256 option_parser = optparse.OptionParser()
257 AddGeneratorOptions(option_parser)
258 options, _ = option_parser.parse_args(argv)
260 if not os.path.exists(options.source):
261 print 'Source project does not exist, please provide correct directory.'
263 out_dir = options.target
265 # Clean directory for project first.
266 CleanLibraryProject(out_dir)
268 out_project_dir = os.path.join(out_dir, LIBRARY_PROJECT_NAME)
269 if not os.path.exists(out_project_dir):
270 os.mkdir(out_project_dir)
272 # Copy Eclipse project files of library project.
273 CopyProjectFiles(options.source, out_dir)
274 # Copy binaries and resuorces.
275 CopyResources(out_dir)
276 CopyBinaries(out_dir)
277 # Copy JS API binding files.
278 CopyJSBindingFiles(options.source, out_dir)
279 # Post copy library project.
280 PostCopyLibraryProject(out_dir)
281 # Remove unused files.
282 mode = os.path.basename(os.path.normpath(out_dir))
283 RemoveUnusedFilesInReleaseMode(mode,
284 os.path.join(out_dir, LIBRARY_PROJECT_NAME, 'libs'))
285 # Create empty src directory
286 src_dir = os.path.join(out_project_dir, 'src')
287 if not os.path.isdir(src_dir):
289 readme = os.path.join(src_dir, 'README.md')
290 open(readme, 'w').write(
291 "# Source folder for xwalk_core_library\n"
292 "## Why it's empty\n"
293 "xwalk_core_library doesn't contain java sources.\n"
294 "## Why put me here\n"
295 "To make archives keep the folder, "
296 "the src directory is needed to build an apk by ant.")
297 print 'Your Android library project has been created at %s' % (
300 if __name__ == '__main__':
301 sys.exit(main(sys.argv))