Push native libraries separately when gyp manages install
When an APK is installed, any native libraries it contains are extracted to the APK's lib folder on the device. It is actually possible to add, change, or remove libraries in that folder directly. This means, that when gyp is managing the install of APKs, the APK does not actually need to include the native library, and that can be pushed separately. This does several nice things: libraries can be pushed while a .apk is building .apk no longer needs to be rebuilt+reinstalled when a library changes if native library isn't changed, it doesn't need to be zipped+installed w/ component build, only changed libraries will need to be reinstalled BUG=158821 Review URL: https://chromiumcodereview.appspot.com/13334003 git-svn-id: http://src.chromium.org/svn/trunk/src/build@191888 4ff67af0-8c30-449e-8e8b-ad334ec8d88c
This commit is contained in:
Родитель
8278ca35b0
Коммит
6bcaee7278
|
@ -0,0 +1,72 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2013 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
"""Creates symlinks to native libraries for an APK.
|
||||
|
||||
The native libraries should have previously been pushed to the device (in
|
||||
options.target_dir). This script then creates links in an apk's lib/ folder to
|
||||
those native libraries.
|
||||
"""
|
||||
|
||||
import json
|
||||
import optparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
BUILD_ANDROID_DIR = os.path.join(os.path.dirname(__file__), '..')
|
||||
sys.path.append(BUILD_ANDROID_DIR)
|
||||
|
||||
from pylib import android_commands
|
||||
from pylib import build_utils
|
||||
from pylib.utils import apk_helper
|
||||
|
||||
|
||||
def CreateLinks(options):
|
||||
libraries = build_utils.ReadJson(options.libraries_json)
|
||||
apk_package = apk_helper.GetPackageName(options.apk)
|
||||
|
||||
# There is a large (~100ms) overhead for each call to adb.RunShellCommand. To
|
||||
# avoid this overhead, craft a single command that creates all the links.
|
||||
link = '/data/data/' + apk_package + '/lib/$f'
|
||||
target = options.target_dir + '/$f'
|
||||
names = ' '.join(libraries)
|
||||
cmd = (
|
||||
'for f in ' + names + '; do \n' +
|
||||
'rm ' + link + ' > /dev/null 2>&1 \n' +
|
||||
'ln -s ' + target + ' ' + link + '\n' +
|
||||
'done'
|
||||
)
|
||||
|
||||
adb = android_commands.AndroidCommands()
|
||||
result = adb.RunShellCommand(cmd)
|
||||
|
||||
if result:
|
||||
raise Exception(
|
||||
'Unexpected output creating links on device.\n' +
|
||||
'\n'.join(result))
|
||||
|
||||
|
||||
def main(argv):
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option('--apk', help='Path to the apk.')
|
||||
parser.add_option('--libraries-json',
|
||||
help='Path to the json list of native libraries.')
|
||||
parser.add_option('--target-dir',
|
||||
help='Device directory that contains the target libraries for symlinks.')
|
||||
parser.add_option('--stamp', help='Path to touch on success.')
|
||||
options, _ = parser.parse_args()
|
||||
|
||||
required_options = ['apk', 'libraries_json', 'target_dir']
|
||||
build_utils.CheckOptions(options, parser, required=required_options)
|
||||
|
||||
CreateLinks(options)
|
||||
|
||||
if options.stamp:
|
||||
build_utils.Touch(options.stamp)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv))
|
|
@ -0,0 +1,55 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2013 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
"""Pushes native libraries to a device.
|
||||
|
||||
"""
|
||||
|
||||
import json
|
||||
import optparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
BUILD_ANDROID_DIR = os.path.join(os.path.dirname(__file__), '..')
|
||||
sys.path.append(BUILD_ANDROID_DIR)
|
||||
|
||||
from pylib import android_commands
|
||||
from pylib import build_utils
|
||||
|
||||
|
||||
def DoPush(options):
|
||||
libraries = build_utils.ReadJson(options.libraries_json)
|
||||
|
||||
adb = android_commands.AndroidCommands()
|
||||
adb.RunShellCommand('mkdir ' + options.device_dir)
|
||||
for lib in libraries:
|
||||
device_path = os.path.join(options.device_dir, lib)
|
||||
host_path = os.path.join(options.libraries_dir, lib)
|
||||
adb.PushIfNeeded(host_path, device_path)
|
||||
|
||||
|
||||
def main(argv):
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option('--libraries-dir',
|
||||
help='Directory that contains stripped libraries.')
|
||||
parser.add_option('--device-dir',
|
||||
help='Device directory to push the libraries to.')
|
||||
parser.add_option('--libraries-json',
|
||||
help='Path to the json list of native libraries.')
|
||||
parser.add_option('--stamp', help='Path to touch on success.')
|
||||
options, _ = parser.parse_args()
|
||||
|
||||
required_options = ['libraries_dir', 'device_dir', 'libraries_json']
|
||||
build_utils.CheckOptions(options, parser, required=required_options)
|
||||
|
||||
DoPush(options)
|
||||
|
||||
if options.stamp:
|
||||
build_utils.Touch(options.stamp)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv))
|
|
@ -45,9 +45,7 @@ def ParseArgs():
|
|||
# Check that required options have been provided.
|
||||
required_options = ('android_sdk', 'android_sdk_tools', 'R_dir', 'res_dirs',
|
||||
'crunch_input_dir', 'crunch_output_dir')
|
||||
for option_name in required_options:
|
||||
if not getattr(options, option_name):
|
||||
parser.error('--%s is required' % option_name.replace('_', '-'))
|
||||
build_utils.CheckOptions(options, parser, required=required_options)
|
||||
|
||||
return options
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
# found in the LICENSE file.
|
||||
|
||||
import fnmatch
|
||||
import json
|
||||
import os
|
||||
import pipes
|
||||
import shlex
|
||||
|
@ -55,6 +56,17 @@ def ParseGypList(gyp_string):
|
|||
return shlex.split(gyp_string)
|
||||
|
||||
|
||||
def CheckOptions(options, parser, required=[]):
|
||||
for option_name in required:
|
||||
if not getattr(options, option_name):
|
||||
parser.error('--%s is required' % option_name.replace('_', '-'))
|
||||
|
||||
|
||||
def ReadJson(path):
|
||||
with open(path, 'r') as jsonfile:
|
||||
return json.load(jsonfile)
|
||||
|
||||
|
||||
# This can be used in most cases like subprocess.check_call. The output,
|
||||
# particularly when the command fails, better highlights the command's failure.
|
||||
# This call will directly exit on a failure in the subprocess so that no python
|
||||
|
|
|
@ -73,8 +73,8 @@
|
|||
'intermediate_dir': '<(PRODUCT_DIR)/<(_target_name)',
|
||||
'asset_location%': '<(intermediate_dir)/assets',
|
||||
'codegen_stamp': '<(intermediate_dir)/codegen.stamp',
|
||||
'compile_input_paths': [ ],
|
||||
'package_input_paths': [ ],
|
||||
'compile_input_paths': [],
|
||||
'package_input_paths': [],
|
||||
'ordered_libraries_file': '<(intermediate_dir)/native_libraries.json',
|
||||
# TODO(cjhopman): build/ shouldn't refer to content/. The libraryloader and
|
||||
# nativelibraries template should be moved out of content/ (to base/?).
|
||||
|
@ -97,6 +97,8 @@
|
|||
'obfuscated_jar_path': '<(intermediate_dir)/obfuscated.jar',
|
||||
'dex_path': '<(intermediate_dir)/classes.dex',
|
||||
'android_manifest': '<(java_in_dir)/AndroidManifest.xml',
|
||||
'push_stamp': '<(intermediate_dir)/push.stamp',
|
||||
'link_stamp': '<(intermediate_dir)/link.stamp',
|
||||
'codegen_input_paths': [],
|
||||
'final_apk_path': '<(PRODUCT_DIR)/apks/<(apk_name).apk',
|
||||
'apk_install_stamp': '<(intermediate_dir)/apk_install.stamp',
|
||||
|
@ -128,7 +130,6 @@
|
|||
'variables': {
|
||||
'compile_input_paths': [ '<(native_libraries_java_stamp)' ],
|
||||
'generated_src_dirs': [ '<(native_libraries_java_dir)' ],
|
||||
'package_input_paths': [ '<(strip_stamp)' ],
|
||||
},
|
||||
'actions': [
|
||||
{
|
||||
|
@ -189,9 +190,6 @@
|
|||
{
|
||||
'action_name': 'strip_native_libraries',
|
||||
'message': 'Stripping libraries for <(_target_name)',
|
||||
'variables': {
|
||||
'apk_libraries_dir': '<(intermediate_dir)/libs/<(android_app_abi)',
|
||||
},
|
||||
'inputs': [
|
||||
'<(DEPTH)/build/android/pylib/build_utils.py',
|
||||
'<(DEPTH)/build/android/strip_library_for_apk.py',
|
||||
|
@ -211,6 +209,62 @@
|
|||
],
|
||||
},
|
||||
],
|
||||
'conditions': [
|
||||
['gyp_managed_install == 1', {
|
||||
'variables': {
|
||||
'apk_libraries_dir': '<(intermediate_dir)/lib.stripped/',
|
||||
'device_library_dir': '/data/local/tmp/chromium/lib.stripped/<(_target_name)',
|
||||
},
|
||||
'dependencies': [
|
||||
'<(DEPTH)/tools/android/md5sum/md5sum.gyp:md5sum',
|
||||
],
|
||||
'actions': [
|
||||
{
|
||||
'action_name': 'push_libraries_<(_target_name)',
|
||||
'message': 'Pushing libraries to device for <(_target_name)',
|
||||
'inputs': [
|
||||
'<(DEPTH)/build/android/pylib/build_utils.py',
|
||||
'<(DEPTH)/build/android/gyp/push_libraries.py',
|
||||
'<(strip_stamp)',
|
||||
],
|
||||
'outputs': [
|
||||
'<(push_stamp)'
|
||||
],
|
||||
'action': [
|
||||
'python', '<(DEPTH)/build/android/gyp/push_libraries.py',
|
||||
'--libraries-dir=<(apk_libraries_dir)',
|
||||
'--device-dir=<(device_library_dir)',
|
||||
'--libraries-json=<(ordered_libraries_file)',
|
||||
'--stamp=<(push_stamp)',
|
||||
],
|
||||
},
|
||||
{
|
||||
'action_name': 'create_library_links',
|
||||
'message': 'Creating links on device for <(_target_name).',
|
||||
'inputs': [
|
||||
'<(DEPTH)/build/android/gyp/create_device_library_links.py',
|
||||
'<(apk_install_stamp)',
|
||||
'<(push_stamp)'
|
||||
],
|
||||
'outputs': [
|
||||
'<(link_stamp)'
|
||||
],
|
||||
'action': [
|
||||
'python', '<(DEPTH)/build/android/gyp/create_device_library_links.py',
|
||||
'--apk=<(final_apk_path)',
|
||||
'--libraries-json=<(ordered_libraries_file)',
|
||||
'--target-dir=<(device_library_dir)',
|
||||
'--stamp=<(link_stamp)',
|
||||
],
|
||||
},
|
||||
],
|
||||
}, {
|
||||
'variables': {
|
||||
'apk_libraries_dir': '<(intermediate_dir)/libs/<(android_app_abi)',
|
||||
'package_input_paths': [ '<(strip_stamp)' ],
|
||||
},
|
||||
}],
|
||||
],
|
||||
}], # native_libs_paths != []
|
||||
['java_strings_grd != ""', {
|
||||
'variables': {
|
||||
|
|
Загрузка…
Ссылка в новой задаче