Merge commit 'upstream-main' into master

Bug: 261600888
Test: none, build files to be updated in follow up cl
Change-Id: Ib520938290c6bbdee4a9f73b6419b6c947a96ec4
This commit is contained in:
Jorge E. Moreira
2022-12-06 16:34:41 -08:00
5393 changed files with 541103 additions and 211666 deletions

View File

@ -1 +1 @@
sakal@webrtc.org
xalep@webrtc.org

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env vpython3
# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
#
@ -7,7 +7,6 @@
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
"""Script to generate libwebrtc.aar for distribution.
The script has to be run from the root src folder.
@ -33,7 +32,6 @@ import sys
import tempfile
import zipfile
SCRIPT_DIR = os.path.dirname(os.path.realpath(sys.argv[0]))
SRC_DIR = os.path.normpath(os.path.join(SCRIPT_DIR, os.pardir, os.pardir))
DEFAULT_ARCHS = ['armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64']
@ -41,8 +39,8 @@ NEEDED_SO_FILES = ['libjingle_peerconnection_so.so']
JAR_FILE = 'lib.java/sdk/android/libwebrtc.jar'
MANIFEST_FILE = 'sdk/android/AndroidManifest.xml'
TARGETS = [
'sdk/android:libwebrtc',
'sdk/android:libjingle_peerconnection_so',
'sdk/android:libwebrtc',
'sdk/android:libjingle_peerconnection_so',
]
sys.path.append(os.path.join(SCRIPT_DIR, '..', 'libs'))
@ -52,32 +50,58 @@ sys.path.append(os.path.join(SRC_DIR, 'build'))
import find_depot_tools
def _ParseArgs():
parser = argparse.ArgumentParser(description='libwebrtc.aar generator.')
parser.add_argument('--build-dir',
parser.add_argument(
'--build-dir',
type=os.path.abspath,
help='Build dir. By default will create and use temporary dir.')
parser.add_argument('--output', default='libwebrtc.aar',
help='Output file of the script.')
parser.add_argument('--arch', default=DEFAULT_ARCHS, nargs='*',
help='Architectures to build. Defaults to %(default)s.')
parser.add_argument('--use-goma', action='store_true', default=False,
help='Use goma.')
parser.add_argument('--verbose', action='store_true', default=False,
help='Debug logging.')
parser.add_argument('--extra-gn-args', default=[], nargs='*',
parser.add_argument('--output',
default='libwebrtc.aar',
type=os.path.abspath,
help='Output file of the script.')
parser.add_argument('--arch',
default=DEFAULT_ARCHS,
nargs='*',
help='Architectures to build. Defaults to %(default)s.')
parser.add_argument('--use-goma',
action='store_true',
default=False,
help='Use goma.')
parser.add_argument('--use-remoteexec',
action='store_true',
default=False,
help='Use RBE.')
parser.add_argument('--use-unstripped-libs',
action='store_true',
default=False,
help='Use unstripped .so files within libwebrtc.aar')
parser.add_argument('--verbose',
action='store_true',
default=False,
help='Debug logging.')
parser.add_argument(
'--extra-gn-args',
default=[],
nargs='*',
help="""Additional GN arguments to be used during Ninja generation.
These are passed to gn inside `--args` switch and
applied after any other arguments and will
override any values defined by the script.
Example of building debug aar file:
build_aar.py --extra-gn-args='is_debug=true'""")
parser.add_argument('--extra-ninja-switches', default=[], nargs='*',
parser.add_argument(
'--extra-ninja-switches',
default=[],
nargs='*',
help="""Additional Ninja switches to be used during compilation.
These are applied after any other Ninja switches.
Example of enabling verbose Ninja output:
build_aar.py --extra-ninja-switches='-v'""")
parser.add_argument('--extra-gn-switches', default=[], nargs='*',
parser.add_argument(
'--extra-gn-switches',
default=[],
nargs='*',
help="""Additional GN switches to be used during compilation.
These are applied after any other GN switches.
Example of enabling verbose GN output:
@ -86,16 +110,20 @@ def _ParseArgs():
def _RunGN(args):
cmd = [sys.executable,
os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'gn.py')]
cmd = [
sys.executable,
os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'gn.py')
]
cmd.extend(args)
logging.debug('Running: %r', cmd)
subprocess.check_call(cmd)
def _RunNinja(output_directory, args):
cmd = [os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'ninja'),
'-C', output_directory]
cmd = [
os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'ninja'), '-C',
output_directory
]
cmd.extend(args)
logging.debug('Running: %r', cmd)
subprocess.check_call(cmd)
@ -105,10 +133,9 @@ def _EncodeForGN(value):
"""Encodes value as a GN literal."""
if isinstance(value, str):
return '"' + value + '"'
elif isinstance(value, bool):
if isinstance(value, bool):
return repr(value).lower()
else:
return repr(value)
return repr(value)
def _GetOutputDirectory(build_dir, arch):
@ -120,53 +147,52 @@ def _GetTargetCpu(arch):
"""Returns target_cpu for the GN build with the given architecture."""
if arch in ['armeabi', 'armeabi-v7a']:
return 'arm'
elif arch == 'arm64-v8a':
if arch == 'arm64-v8a':
return 'arm64'
elif arch == 'x86':
if arch == 'x86':
return 'x86'
elif arch == 'x86_64':
if arch == 'x86_64':
return 'x64'
else:
raise Exception('Unknown arch: ' + arch)
raise Exception('Unknown arch: ' + arch)
def _GetArmVersion(arch):
"""Returns arm_version for the GN build with the given architecture."""
if arch == 'armeabi':
return 6
elif arch == 'armeabi-v7a':
if arch == 'armeabi-v7a':
return 7
elif arch in ['arm64-v8a', 'x86', 'x86_64']:
if arch in ['arm64-v8a', 'x86', 'x86_64']:
return None
else:
raise Exception('Unknown arch: ' + arch)
raise Exception('Unknown arch: ' + arch)
def Build(build_dir, arch, use_goma, extra_gn_args, extra_gn_switches,
extra_ninja_switches):
def Build(build_dir, arch, use_goma, use_remoteexec, extra_gn_args,
extra_gn_switches, extra_ninja_switches):
"""Generates target architecture using GN and builds it using ninja."""
logging.info('Building: %s', arch)
output_directory = _GetOutputDirectory(build_dir, arch)
gn_args = {
'target_os': 'android',
'is_debug': False,
'is_component_build': False,
'rtc_include_tests': False,
'target_cpu': _GetTargetCpu(arch),
'use_goma': use_goma
'target_os': 'android',
'is_debug': False,
'is_component_build': False,
'rtc_include_tests': False,
'target_cpu': _GetTargetCpu(arch),
'use_goma': use_goma,
'use_remoteexec': use_remoteexec,
}
arm_version = _GetArmVersion(arch)
if arm_version:
gn_args['arm_version'] = arm_version
gn_args_str = '--args=' + ' '.join([
k + '=' + _EncodeForGN(v) for k, v in gn_args.items()] + extra_gn_args)
gn_args_str = '--args=' + ' '.join(
[k + '=' + _EncodeForGN(v) for k, v in gn_args.items()] + extra_gn_args)
gn_args_list = ['gen', output_directory, gn_args_str]
gn_args_list.extend(extra_gn_switches)
_RunGN(gn_args_list)
ninja_args = TARGETS[:]
if use_goma:
if use_goma or use_remoteexec:
ninja_args.extend(['-j', '200'])
ninja_args.extend(extra_ninja_switches)
_RunNinja(output_directory, ninja_args)
@ -180,14 +206,16 @@ def CollectCommon(aar_file, build_dir, arch):
aar_file.write(os.path.join(output_directory, JAR_FILE), 'classes.jar')
def Collect(aar_file, build_dir, arch):
def Collect(aar_file, build_dir, arch, unstripped):
"""Collects architecture specific files into the .aar-archive."""
logging.info('Collecting: %s', arch)
output_directory = _GetOutputDirectory(build_dir, arch)
abi_dir = os.path.join('jni', arch)
for so_file in NEEDED_SO_FILES:
aar_file.write(os.path.join(output_directory, so_file),
source_so_file = os.path.join("lib.unstripped",
so_file) if unstripped else so_file
aar_file.write(os.path.join(output_directory, source_so_file),
os.path.join(abi_dir, so_file))
@ -197,23 +225,29 @@ def GenerateLicenses(output_dir, build_dir, archs):
builder.GenerateLicenseText(output_dir)
def BuildAar(archs, output_file, use_goma=False, extra_gn_args=None,
ext_build_dir=None, extra_gn_switches=None,
extra_ninja_switches=None):
def BuildAar(archs,
output_file,
use_goma=False,
use_remoteexec=False,
extra_gn_args=None,
ext_build_dir=None,
extra_gn_switches=None,
extra_ninja_switches=None,
unstripped=False):
extra_gn_args = extra_gn_args or []
extra_gn_switches = extra_gn_switches or []
extra_ninja_switches = extra_ninja_switches or []
build_dir = ext_build_dir if ext_build_dir else tempfile.mkdtemp()
for arch in archs:
Build(build_dir, arch, use_goma, extra_gn_args, extra_gn_switches,
extra_ninja_switches)
Build(build_dir, arch, use_goma, use_remoteexec, extra_gn_args,
extra_gn_switches, extra_ninja_switches)
with zipfile.ZipFile(output_file, 'w') as aar_file:
# Architecture doesn't matter here, arbitrarily using the first one.
CollectCommon(aar_file, build_dir, archs[0])
for arch in archs:
Collect(aar_file, build_dir, arch)
Collect(aar_file, build_dir, arch, unstripped)
license_dir = os.path.dirname(os.path.realpath(output_file))
GenerateLicenses(license_dir, build_dir, archs)
@ -226,8 +260,9 @@ def main():
args = _ParseArgs()
logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO)
BuildAar(args.arch, args.output, args.use_goma, args.extra_gn_args,
args.build_dir, args.extra_gn_switches, args.extra_ninja_switches)
BuildAar(args.arch, args.output, args.use_goma, args.use_remoteexec,
args.extra_gn_args, args.build_dir, args.extra_gn_switches,
args.extra_ninja_switches, args.use_unstripped_libs)
if __name__ == '__main__':

View File

@ -1,291 +0,0 @@
#!/usr/bin/env python
# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
"""Script for publishing WebRTC AAR on Bintray.
Set BINTRAY_USER and BINTRAY_API_KEY environment variables before running
this script for authentication.
"""
import argparse
import json
import logging
import os
import re
import shutil
import subprocess
import sys
import tempfile
import time
SCRIPT_DIR = os.path.dirname(os.path.realpath(sys.argv[0]))
CHECKOUT_ROOT = os.path.abspath(os.path.join(SCRIPT_DIR, os.pardir, os.pardir))
sys.path.append(os.path.join(CHECKOUT_ROOT, 'third_party'))
import requests
import jinja2
sys.path.append(os.path.join(CHECKOUT_ROOT, 'tools_webrtc'))
from android.build_aar import BuildAar
ARCHS = ['armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64']
MAVEN_REPOSITORY = 'https://google.bintray.com/webrtc'
API = 'https://api.bintray.com'
PACKAGE_PATH = 'google/webrtc/google-webrtc'
CONTENT_API = API + '/content/' + PACKAGE_PATH
PACKAGES_API = API + '/packages/' + PACKAGE_PATH
GROUP_ID = 'org/webrtc'
ARTIFACT_ID = 'google-webrtc'
COMMIT_POSITION_REGEX = r'^Cr-Commit-Position: refs/heads/master@{#(\d+)}$'
API_TIMEOUT_SECONDS = 10.0
UPLOAD_TRIES = 3
# The sleep time is increased exponentially.
UPLOAD_RETRY_BASE_SLEEP_SECONDS = 2.0
GRADLEW_BIN = os.path.join(CHECKOUT_ROOT,
'examples/androidtests/third_party/gradle/gradlew')
ADB_BIN = os.path.join(CHECKOUT_ROOT,
'third_party/android_sdk/public/platform-tools/adb')
AAR_PROJECT_DIR = os.path.join(CHECKOUT_ROOT, 'examples/aarproject')
AAR_PROJECT_GRADLE = os.path.join(AAR_PROJECT_DIR, 'build.gradle')
AAR_PROJECT_APP_GRADLE = os.path.join(AAR_PROJECT_DIR, 'app', 'build.gradle')
AAR_PROJECT_DEPENDENCY = "implementation 'org.webrtc:google-webrtc:1.0.+'"
AAR_PROJECT_VERSION_DEPENDENCY = "implementation 'org.webrtc:google-webrtc:%s'"
def _ParseArgs():
parser = argparse.ArgumentParser(description='Releases WebRTC on Bintray.')
parser.add_argument('--use-goma', action='store_true', default=False,
help='Use goma.')
parser.add_argument('--skip-tests', action='store_true', default=False,
help='Skips running the tests.')
parser.add_argument('--publish', action='store_true', default=False,
help='Automatically publishes the library if the tests pass.')
parser.add_argument('--build-dir', default=None,
help='Temporary directory to store the build files. If not specified, '
'a new directory will be created.')
parser.add_argument('--verbose', action='store_true', default=False,
help='Debug logging.')
return parser.parse_args()
def _GetCommitHash():
commit_hash = subprocess.check_output(
['git', 'rev-parse', 'HEAD'], cwd=CHECKOUT_ROOT).strip()
return commit_hash
def _GetCommitPos():
commit_message = subprocess.check_output(
['git', 'rev-list', '--format=%B', '--max-count=1', 'HEAD'],
cwd=CHECKOUT_ROOT)
commit_pos_match = re.search(
COMMIT_POSITION_REGEX, commit_message, re.MULTILINE)
if not commit_pos_match:
raise Exception('Commit position not found in the commit message: %s'
% commit_message)
return commit_pos_match.group(1)
def _UploadFile(user, password, filename, version, target_file):
# URL is of format:
# <repository_api>/<version>/<group_id>/<artifact_id>/<version>/<target_file>
# Example:
# https://api.bintray.com/content/google/webrtc/google-webrtc/1.0.19742/org/webrtc/google-webrtc/1.0.19742/google-webrtc-1.0.19742.aar
target_dir = version + '/' + GROUP_ID + '/' + ARTIFACT_ID + '/' + version
target_path = target_dir + '/' + target_file
url = CONTENT_API + '/' + target_path
logging.info('Uploading %s to %s', filename, url)
with open(filename) as fh:
file_data = fh.read()
for attempt in xrange(UPLOAD_TRIES):
try:
response = requests.put(url, data=file_data, auth=(user, password),
timeout=API_TIMEOUT_SECONDS)
break
except requests.exceptions.Timeout as e:
logging.warning('Timeout while uploading: %s', e)
time.sleep(UPLOAD_RETRY_BASE_SLEEP_SECONDS ** attempt)
else:
raise Exception('Failed to upload %s' % filename)
if not response.ok:
raise Exception('Failed to upload %s. Response: %s' % (filename, response))
logging.info('Uploaded %s: %s', filename, response)
def _GeneratePom(target_file, version, commit):
env = jinja2.Environment(
loader=jinja2.PackageLoader('release_aar'),
)
template = env.get_template('pom.jinja')
pom = template.render(version=version, commit=commit)
with open(target_file, 'w') as fh:
fh.write(pom)
def _TestAAR(tmp_dir, username, password, version):
"""Runs AppRTCMobile tests using the AAR. Returns true if the tests pass."""
logging.info('Testing library.')
env = jinja2.Environment(
loader=jinja2.PackageLoader('release_aar'),
)
gradle_backup = os.path.join(tmp_dir, 'build.gradle.backup')
app_gradle_backup = os.path.join(tmp_dir, 'app-build.gradle.backup')
# Make backup copies of the project files before modifying them.
shutil.copy2(AAR_PROJECT_GRADLE, gradle_backup)
shutil.copy2(AAR_PROJECT_APP_GRADLE, app_gradle_backup)
try:
maven_repository_template = env.get_template('maven-repository.jinja')
maven_repository = maven_repository_template.render(
url=MAVEN_REPOSITORY, username=username, password=password)
# Append Maven repository to build file to download unpublished files.
with open(AAR_PROJECT_GRADLE, 'a') as gradle_file:
gradle_file.write(maven_repository)
# Read app build file.
with open(AAR_PROJECT_APP_GRADLE, 'r') as gradle_app_file:
gradle_app = gradle_app_file.read()
if AAR_PROJECT_DEPENDENCY not in gradle_app:
raise Exception(
'%s not found in the build file.' % AAR_PROJECT_DEPENDENCY)
# Set version to the version to be tested.
target_dependency = AAR_PROJECT_VERSION_DEPENDENCY % version
gradle_app = gradle_app.replace(AAR_PROJECT_DEPENDENCY, target_dependency)
# Write back.
with open(AAR_PROJECT_APP_GRADLE, 'w') as gradle_app_file:
gradle_app_file.write(gradle_app)
# Uninstall any existing version of AppRTCMobile.
logging.info('Uninstalling previous AppRTCMobile versions. It is okay for '
'these commands to fail if AppRTCMobile is not installed.')
subprocess.call([ADB_BIN, 'uninstall', 'org.appspot.apprtc'])
subprocess.call([ADB_BIN, 'uninstall', 'org.appspot.apprtc.test'])
# Run tests.
try:
# First clean the project.
subprocess.check_call([GRADLEW_BIN, 'clean'], cwd=AAR_PROJECT_DIR)
# Then run the tests.
subprocess.check_call([GRADLEW_BIN, 'connectedDebugAndroidTest'],
cwd=AAR_PROJECT_DIR)
except subprocess.CalledProcessError:
logging.exception('Test failure.')
return False # Clean or tests failed
return True # Tests pass
finally:
# Restore backups.
shutil.copy2(gradle_backup, AAR_PROJECT_GRADLE)
shutil.copy2(app_gradle_backup, AAR_PROJECT_APP_GRADLE)
def _PublishAAR(user, password, version, additional_args):
args = {
'publish_wait_for_secs': 0 # Publish asynchronously.
}
args.update(additional_args)
url = CONTENT_API + '/' + version + '/publish'
response = requests.post(url, data=json.dumps(args), auth=(user, password),
timeout=API_TIMEOUT_SECONDS)
if not response.ok:
raise Exception('Failed to publish. Response: %s' % response)
def _DeleteUnpublishedVersion(user, password, version):
url = PACKAGES_API + '/versions/' + version
response = requests.get(url, auth=(user, password),
timeout=API_TIMEOUT_SECONDS)
if not response.ok:
raise Exception('Failed to get version info. Response: %s' % response)
version_info = json.loads(response.content)
if version_info['published']:
logging.info('Version has already been published, not deleting.')
return
logging.info('Deleting unpublished version.')
response = requests.delete(url, auth=(user, password),
timeout=API_TIMEOUT_SECONDS)
if not response.ok:
raise Exception('Failed to delete version. Response: %s' % response)
def ReleaseAar(use_goma, skip_tests, publish, build_dir):
version = '1.0.' + _GetCommitPos()
commit = _GetCommitHash()
logging.info('Releasing AAR version %s with hash %s', version, commit)
user = os.environ.get('BINTRAY_USER', None)
api_key = os.environ.get('BINTRAY_API_KEY', None)
if not user or not api_key:
raise Exception('Environment variables BINTRAY_USER and BINTRAY_API_KEY '
'must be defined.')
# If build directory is not specified, create a temporary directory.
use_tmp_dir = not build_dir
if use_tmp_dir:
build_dir = tempfile.mkdtemp()
try:
base_name = ARTIFACT_ID + '-' + version
aar_file = os.path.join(build_dir, base_name + '.aar')
third_party_licenses_file = os.path.join(build_dir, 'LICENSE.md')
pom_file = os.path.join(build_dir, base_name + '.pom')
logging.info('Building at %s', build_dir)
BuildAar(ARCHS, aar_file,
use_goma=use_goma,
ext_build_dir=os.path.join(build_dir, 'aar-build'))
_GeneratePom(pom_file, version, commit)
_UploadFile(user, api_key, aar_file, version, base_name + '.aar')
_UploadFile(user, api_key, third_party_licenses_file, version,
'THIRD_PARTY_LICENSES.md')
_UploadFile(user, api_key, pom_file, version, base_name + '.pom')
tests_pass = skip_tests or _TestAAR(build_dir, user, api_key, version)
if not tests_pass:
logging.info('Discarding library.')
_PublishAAR(user, api_key, version, {'discard': True})
_DeleteUnpublishedVersion(user, api_key, version)
raise Exception('Test failure. Discarded library.')
if publish:
logging.info('Publishing library.')
_PublishAAR(user, api_key, version, {})
else:
logging.info('Note: The library has not not been published automatically.'
' Please do so manually if desired.')
finally:
if use_tmp_dir:
shutil.rmtree(build_dir, True)
def main():
args = _ParseArgs()
logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO)
ReleaseAar(args.use_goma, args.skip_tests, args.publish, args.build_dir)
if __name__ == '__main__':
sys.exit(main())

View File

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<lint>
<!-- These lint settings is for the Android linter that gets run by
lint_action.gypi on compile of WebRTC java code. All WebRTC java code
should lint cleanly for the issues below. -->
<!-- TODO(phoglund): make work with suppress.py or remove printout referring
to suppress.py. -->
<issue id="UseSparseArrays" severity="ignore"/>
<issue id="Registered" severity="ignore"/>
<issue id="MissingPermission" severity="ignore"/>
<issue id="ApplySharedPref" severity="ignore"/>
<issue id="UnusedResources" severity="ignore"/>
<issue id="IconColors" severity="ignore"/>
<issue id="IconDipSize" severity="ignore"/>
<issue id="IconDuplicatesConfig" severity="ignore"/>
<issue id="RelativeOverlap" severity="ignore"/>
<issue id="RtlCompat" severity="ignore"/>
<issue id="IconMissingDensityFolder" severity="ignore"/>
<issue id="OldTargetApi" severity="ignore"/>
<issue id="GoogleAppIndexingWarning" severity="ignore"/>
<issue id="MissingRegistered" severity="ignore"/>
<issue id="LintError">
<!-- We no longer supply class files to lint. -->
<ignore regexp="No `.class` files were found in project"/>
</issue>
<!-- These are just from the dummy AndroidManifest.xml we use for linting.
It's in the same directory as this file. -->
<issue id="MissingApplicationIcon" severity="ignore"/>
<issue id="AllowBackup" severity="ignore"/>
<issue id="MissingVersion" severity="ignore"/>
<!-- Ignore all lint errors in Chromium code. -->
<issue id="all">
<ignore path="**/org/chromium/**/*.java" />
</issue>
<issue id="UsesMinSdkAttributes">
<!-- TODO(oprypin): find a way to disable this warning just for Chromium's
code, not globally. Due to https://cs.chromium.org/lint_manifest_path
it is impossible to discern paths of AndroidManifest.xml files.-->
<ignore path="AndroidManifest.xml" />
</issue>
<issue id="NewApi">
<!-- This is rewritten by desugar after lint runs. -->
<ignore regexp="Call requires API level 19.*`java.util.Objects#requireNonNull`"/>
<!-- AutoCloseable has been available since API 15, just hidden. -->
<ignore regexp="Class requires API level 19.*java.lang.AutoCloseable"/>
<ignore regexp="Call requires API level 19.*java.lang.AutoCloseable#close"/>
<!-- We support try-with-resources via desugar. -->
<ignore regexp="Try-with-resources requires API level 19"/>
<ignore regexp="Call requires API level 19.*`java.lang.Throwable#addSuppressed`"/>
<!-- We support new language features via desugar. -->
<ignore regexp="Default method requires API level 24"/>
<ignore regexp="Static interface method requires API level 24"/>
</issue>
</lint>

143
tools_webrtc/android/test_aar.py Executable file
View File

@ -0,0 +1,143 @@
#!/usr/bin/env vpython3
# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
"""Script for building and testing WebRTC AAR."""
import argparse
import logging
import os
import re
import shutil
import subprocess
import sys
import tempfile
SCRIPT_DIR = os.path.dirname(os.path.realpath(sys.argv[0]))
CHECKOUT_ROOT = os.path.abspath(os.path.join(SCRIPT_DIR, os.pardir, os.pardir))
sys.path.append(os.path.join(CHECKOUT_ROOT, 'tools_webrtc'))
from android.build_aar import BuildAar
ARCHS = ['armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64']
ARTIFACT_ID = 'google-webrtc'
COMMIT_POSITION_REGEX = r'^Cr-Commit-Position: refs/heads/master@{#(\d+)}$'
GRADLEW_BIN = os.path.join(CHECKOUT_ROOT,
'examples/androidtests/third_party/gradle/gradlew')
ADB_BIN = os.path.join(CHECKOUT_ROOT,
'third_party/android_sdk/public/platform-tools/adb')
AAR_PROJECT_DIR = os.path.join(CHECKOUT_ROOT, 'examples/aarproject')
def _ParseArgs():
parser = argparse.ArgumentParser(description='Releases WebRTC on Bintray.')
parser.add_argument('--use-goma',
action='store_true',
default=False,
help='Use goma.')
parser.add_argument('--skip-tests',
action='store_true',
default=False,
help='Skips running the tests.')
parser.add_argument(
'--build-dir',
default=None,
help='Temporary directory to store the build files. If not specified, '
'a new directory will be created.')
parser.add_argument('--verbose',
action='store_true',
default=False,
help='Debug logging.')
return parser.parse_args()
def _GetCommitHash():
commit_hash = subprocess.check_output(
['git', 'rev-parse', 'HEAD'], cwd=CHECKOUT_ROOT).decode('UTF-8').strip()
return commit_hash
def _GetCommitPos():
commit_message = subprocess.check_output(
['git', 'rev-list', '--format=%B', '--max-count=1', 'HEAD'],
cwd=CHECKOUT_ROOT).decode('UTF-8')
commit_pos_match = re.search(COMMIT_POSITION_REGEX, commit_message,
re.MULTILINE)
if not commit_pos_match:
raise Exception('Commit position not found in the commit message: %s' %
commit_message)
return commit_pos_match.group(1)
def _TestAAR(build_dir):
"""Runs AppRTCMobile tests using the AAR. Returns true if the tests pass."""
logging.info('Testing library.')
# Uninstall any existing version of AppRTCMobile.
logging.info('Uninstalling previous AppRTCMobile versions. It is okay for '
'these commands to fail if AppRTCMobile is not installed.')
subprocess.call([ADB_BIN, 'uninstall', 'org.appspot.apprtc'])
subprocess.call([ADB_BIN, 'uninstall', 'org.appspot.apprtc.test'])
# Run tests.
try:
# First clean the project.
subprocess.check_call([GRADLEW_BIN, 'clean'], cwd=AAR_PROJECT_DIR)
# Then run the tests.
subprocess.check_call([
GRADLEW_BIN, 'connectedDebugAndroidTest',
'-PaarDir=' + os.path.abspath(build_dir)
],
cwd=AAR_PROJECT_DIR)
except subprocess.CalledProcessError:
logging.exception('Test failure.')
return False # Clean or tests failed
return True # Tests pass
def BuildAndTestAar(use_goma, skip_tests, build_dir):
version = '1.0.' + _GetCommitPos()
commit = _GetCommitHash()
logging.info('Building and Testing AAR version %s with hash %s', version,
commit)
# If build directory is not specified, create a temporary directory.
use_tmp_dir = not build_dir
if use_tmp_dir:
build_dir = tempfile.mkdtemp()
try:
base_name = ARTIFACT_ID + '-' + version
aar_file = os.path.join(build_dir, base_name + '.aar')
logging.info('Building at %s', build_dir)
BuildAar(ARCHS,
aar_file,
use_goma=use_goma,
ext_build_dir=os.path.join(build_dir, 'aar-build'))
tests_pass = skip_tests or _TestAAR(build_dir)
if not tests_pass:
raise Exception('Test failure.')
logging.info('Test success.')
finally:
if use_tmp_dir:
shutil.rmtree(build_dir, True)
def main():
args = _ParseArgs()
logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO)
BuildAndTestAar(args.use_goma, args.skip_tests, args.build_dir)
if __name__ == '__main__':
sys.exit(main())