Commit 028b3b68 authored by Tibor Goldschwendt's avatar Tibor Goldschwendt Committed by Commit Bot

[aab] Add build_config for Android App Bundles

Also, add android_app_bundle_module type to build config.

Bug: 862696
Change-Id: Ic893f47d44d8dd98ff7e70d3a8e09cbf2ce5a444
Reviewed-on: https://chromium-review.googlesource.com/1135834
Commit-Queue: Tibor Goldschwendt <tiborg@chromium.org>
Reviewed-by: default avataragrieve <agrieve@chromium.org>
Cr-Commit-Position: refs/heads/master@{#577305}
parent ed3020b1
...@@ -419,15 +419,15 @@ The list of all `deps_info['java_sources_file']` entries for all library ...@@ -419,15 +419,15 @@ The list of all `deps_info['java_sources_file']` entries for all library
dependencies for this APK. Note: this is a list of files, where each file dependencies for this APK. Note: this is a list of files, where each file
contains a list of Java source files. This is used for JNI registration. contains a list of Java source files. This is used for JNI registration.
* `deps_info['proguard_all_configs"]`: * `deps_info['proguard_all_configs']`:
The collection of all 'deps_info['proguard_configs']` values from this target The collection of all 'deps_info['proguard_configs']` values from this target
and all its dependencies. and all its dependencies.
* `deps_info['proguard_all_extra_jars"]`: * `deps_info['proguard_classpath_jars']`:
The collection of all 'deps_info['extra_classpath_jars']` values from all The collection of all 'deps_info['extra_classpath_jars']` values from all
dependencies. dependencies.
* `deps_info['proguard_under_test_mapping"]`: * `deps_info['proguard_under_test_mapping']`:
Applicable to apks with proguard enabled that have an apk_under_test. This is Applicable to apks with proguard enabled that have an apk_under_test. This is
the path to the apk_under_test's output proguard .mapping file. the path to the apk_under_test's output proguard .mapping file.
...@@ -508,8 +508,8 @@ import xml.dom.minidom ...@@ -508,8 +508,8 @@ import xml.dom.minidom
from util import build_utils from util import build_utils
# Types that should never be used as a dependency of another build config. # Types that should never be used as a dependency of another build config.
_ROOT_TYPES = ('android_apk', 'java_binary', _ROOT_TYPES = ('android_apk', 'java_binary', 'java_annotation_processor',
'java_annotation_processor', 'junit_binary', 'resource_rewriter') 'junit_binary', 'resource_rewriter', 'android_app_bundle')
# Types that should not allow code deps to pass through. # Types that should not allow code deps to pass through.
_RESOURCE_TYPES = ('android_assets', 'android_resources', 'system_java_library') _RESOURCE_TYPES = ('android_assets', 'android_resources', 'system_java_library')
...@@ -888,6 +888,8 @@ def main(argv): ...@@ -888,6 +888,8 @@ def main(argv):
required_options_map = { required_options_map = {
'android_apk': ['build_config', 'dex_path', 'final_dex_path'] + \ 'android_apk': ['build_config', 'dex_path', 'final_dex_path'] + \
jar_path_options, jar_path_options,
'android_app_bundle_module': ['build_config', 'dex_path',
'final_dex_path'] + jar_path_options,
'android_assets': ['build_config'], 'android_assets': ['build_config'],
'android_resources': ['build_config', 'resources_zip'], 'android_resources': ['build_config', 'resources_zip'],
'dist_aar': ['build_config'], 'dist_aar': ['build_config'],
...@@ -899,6 +901,7 @@ def main(argv): ...@@ -899,6 +901,7 @@ def main(argv):
'junit_binary': ['build_config'], 'junit_binary': ['build_config'],
'resource_rewriter': ['build_config'], 'resource_rewriter': ['build_config'],
'system_java_library': ['build_config'], 'system_java_library': ['build_config'],
'android_app_bundle': ['build_config'],
} }
required_options = required_options_map.get(options.type) required_options = required_options_map.get(options.type)
if not required_options: if not required_options:
...@@ -907,14 +910,18 @@ def main(argv): ...@@ -907,14 +910,18 @@ def main(argv):
build_utils.CheckOptions(options, parser, required_options) build_utils.CheckOptions(options, parser, required_options)
if options.apk_proto_resources: if options.apk_proto_resources:
if options.type != 'android_apk': if options.type != 'android_app_bundle_module':
raise Exception('--apk-proto-resources can only be used with ' raise Exception('--apk-proto-resources can only be used with '
'--type=android_apk') '--type=android_app_bundle_module')
is_apk_or_module_target = options.type in ('android_apk',
'android_app_bundle_module')
if options.uncompress_shared_libraries: if options.uncompress_shared_libraries:
if options.type != 'android_apk': if not is_apk_or_module_target:
raise Exception('--uncompressed-shared-libraries can only be used ' raise Exception('--uncompressed-shared-libraries can only be used '
'with --type=android_apk') 'with --type=android_apk or '
'--type=android_app_bundle_module')
if options.jar_path and options.supports_android and not options.dex_path: if options.jar_path and options.supports_android and not options.dex_path:
raise Exception('java_library that supports Android requires a dex path.') raise Exception('java_library that supports Android requires a dex path.')
...@@ -930,7 +937,7 @@ def main(argv): ...@@ -930,7 +937,7 @@ def main(argv):
is_java_target = options.type in ( is_java_target = options.type in (
'java_binary', 'junit_binary', 'java_annotation_processor', 'java_binary', 'junit_binary', 'java_annotation_processor',
'java_library', 'android_apk', 'dist_aar', 'dist_jar', 'java_library', 'android_apk', 'dist_aar', 'dist_jar',
'system_java_library') 'system_java_library', 'android_app_bundle_module')
deps = _DepsFromPaths( deps = _DepsFromPaths(
build_utils.ParseGnList(options.deps_configs), options.type) build_utils.ParseGnList(options.deps_configs), options.type)
...@@ -1001,7 +1008,7 @@ def main(argv): ...@@ -1001,7 +1008,7 @@ def main(argv):
else: else:
gradle['dependent_java_projects'].append(c['path']) gradle['dependent_java_projects'].append(c['path'])
if options.type == 'android_apk': if is_apk_or_module_target:
config['jni'] = {} config['jni'] = {}
all_java_sources = [c['java_sources_file'] for c in all_library_deps all_java_sources = [c['java_sources_file'] for c in all_library_deps
if 'java_sources_file' in c] if 'java_sources_file' in c]
...@@ -1120,7 +1127,7 @@ def main(argv): ...@@ -1120,7 +1127,7 @@ def main(argv):
if options.type in ( if options.type in (
'android_resources', 'android_apk', 'junit_binary', 'resource_rewriter', 'android_resources', 'android_apk', 'junit_binary', 'resource_rewriter',
'dist_aar'): 'dist_aar', 'android_app_bundle_module'):
config['resources'] = {} config['resources'] = {}
config['resources']['dependency_zips'] = [ config['resources']['dependency_zips'] = [
c['resources_zip'] for c in all_resources_deps] c['resources_zip'] for c in all_resources_deps]
...@@ -1135,7 +1142,7 @@ def main(argv): ...@@ -1135,7 +1142,7 @@ def main(argv):
config['resources']['extra_package_names'] = extra_package_names config['resources']['extra_package_names'] = extra_package_names
config['resources']['extra_r_text_files'] = extra_r_text_files config['resources']['extra_r_text_files'] = extra_r_text_files
if options.type == 'android_apk': if is_apk_or_module_target:
deps_dex_files = [c['dex_path'] for c in all_library_deps] deps_dex_files = [c['dex_path'] for c in all_library_deps]
if is_java_target: if is_java_target:
...@@ -1154,11 +1161,6 @@ def main(argv): ...@@ -1154,11 +1161,6 @@ def main(argv):
# The classpath used for bytecode-rewritting. # The classpath used for bytecode-rewritting.
javac_full_classpath = [ javac_full_classpath = [
c['unprocessed_jar_path'] for c in all_library_deps] c['unprocessed_jar_path'] for c in all_library_deps]
# The classpath to use to run this target (or as an input to ProGuard).
java_full_classpath = []
if options.jar_path:
java_full_classpath.append(options.jar_path)
java_full_classpath.extend(c['jar_path'] for c in all_library_deps)
# Deps to add to the compile-time classpath (but not the runtime classpath). # Deps to add to the compile-time classpath (but not the runtime classpath).
# TODO(agrieve): Might be less confusing to fold these into bootclasspath. # TODO(agrieve): Might be less confusing to fold these into bootclasspath.
...@@ -1179,23 +1181,57 @@ def main(argv): ...@@ -1179,23 +1181,57 @@ def main(argv):
if extra_jars: if extra_jars:
deps_info['extra_classpath_jars'] = extra_jars deps_info['extra_classpath_jars'] = extra_jars
if is_java_target or options.type == 'android_app_bundle':
# The classpath to use to run this target (or as an input to ProGuard).
java_full_classpath = []
if is_java_target and options.jar_path:
java_full_classpath.append(options.jar_path)
java_full_classpath.extend(c['jar_path'] for c in all_library_deps)
system_jars = [c['jar_path'] for c in system_library_deps]
system_interface_jars = [c['interface_jar_path'] for c in system_library_deps]
if system_library_deps:
config['android'] = {}
config['android']['sdk_interface_jars'] = system_interface_jars
config['android']['sdk_jars'] = system_jars
gradle['bootclasspath'] = system_jars
if options.proguard_configs: if options.proguard_configs:
deps_info['proguard_configs'] = ( deps_info['proguard_configs'] = (
build_utils.ParseGnList(options.proguard_configs)) build_utils.ParseGnList(options.proguard_configs))
if options.type in ('android_apk', 'dist_aar', 'dist_jar'): if options.type in ('android_apk', 'dist_aar',
'dist_jar', 'android_app_bundle_module', 'android_app_bundle'):
all_configs = deps_info.get('proguard_configs', []) all_configs = deps_info.get('proguard_configs', [])
extra_jars = [] extra_jars = list(system_jars)
for c in all_library_deps: for c in all_library_deps:
all_configs.extend( all_configs.extend(
p for p in c.get('proguard_configs', []) if p not in all_configs) p for p in c.get('proguard_configs', []) if p not in all_configs)
extra_jars.extend( extra_jars.extend(
p for p in c.get('extra_classpath_jars', []) if p not in extra_jars) p for p in c.get('extra_classpath_jars', []) if p not in extra_jars)
deps_info['proguard_all_configs'] = all_configs deps_info['proguard_all_configs'] = all_configs
deps_info['proguard_all_extra_jars'] = extra_jars deps_info['proguard_classpath_jars'] = extra_jars
deps_info['proguard_enabled'] = options.proguard_enabled
if options.proguard_output_jar_path: if options.type == 'android_app_bundle':
deps_info['proguard_output_jar_path'] = options.proguard_output_jar_path deps_proguard_enabled = []
deps_proguard_disabled = []
for d in deps.Direct('android_app_bundle_module'):
if not d['java_runtime_classpath']:
# We don't care about modules that have no Java code for proguarding.
continue
if d['proguard_enabled']:
deps_proguard_enabled.append(d['name'])
else:
deps_proguard_disabled.append(d['name'])
if deps_proguard_enabled and deps_proguard_disabled:
raise Exception('Deps %s have proguard enabled while deps %s have '
'proguard disabled' % (deps_proguard_enabled,
deps_proguard_disabled))
deps_info['sync_proguard_enabled'] = bool(deps_proguard_enabled)
else:
deps_info['proguard_enabled'] = bool(options.proguard_enabled)
if options.proguard_output_jar_path:
deps_info['proguard_output_jar_path'] = options.proguard_output_jar_path
# The java code for an instrumentation test apk is assembled differently for # The java code for an instrumentation test apk is assembled differently for
# ProGuard vs. non-ProGuard. # ProGuard vs. non-ProGuard.
...@@ -1220,7 +1256,7 @@ def main(argv): ...@@ -1220,7 +1256,7 @@ def main(argv):
# Mutating lists, so no need to explicitly re-assign to dict. # Mutating lists, so no need to explicitly re-assign to dict.
all_configs.extend(p for p in tested_apk_config['proguard_all_configs'] all_configs.extend(p for p in tested_apk_config['proguard_all_configs']
if p not in all_configs) if p not in all_configs)
extra_jars.extend(p for p in tested_apk_config['proguard_all_extra_jars'] extra_jars.extend(p for p in tested_apk_config['proguard_classpath_jars']
if p not in extra_jars) if p not in extra_jars)
tested_apk_config = GetDepConfig(options.tested_apk_config) tested_apk_config = GetDepConfig(options.tested_apk_config)
deps_info['proguard_under_test_mapping'] = ( deps_info['proguard_under_test_mapping'] = (
...@@ -1263,20 +1299,12 @@ def main(argv): ...@@ -1263,20 +1299,12 @@ def main(argv):
p for p in deps_dex_files if not p in tested_apk_deps_dex_files] p for p in deps_dex_files if not p in tested_apk_deps_dex_files]
# Dependencies for the final dex file of an apk. # Dependencies for the final dex file of an apk.
if options.type == 'android_apk': if is_apk_or_module_target:
config['final_dex'] = {} config['final_dex'] = {}
dex_config = config['final_dex'] dex_config = config['final_dex']
dex_config['dependency_dex_files'] = deps_dex_files dex_config['dependency_dex_files'] = deps_dex_files
dex_config['path'] = options.final_dex_path dex_config['path'] = options.final_dex_path
system_jars = [c['jar_path'] for c in system_library_deps]
system_interface_jars = [c['interface_jar_path'] for c in system_library_deps]
if system_library_deps:
config['android'] = {}
config['android']['sdk_interface_jars'] = system_interface_jars
config['android']['sdk_jars'] = system_jars
gradle['bootclasspath'] = system_jars
if is_java_target: if is_java_target:
config['javac']['bootclasspath'] = system_jars config['javac']['bootclasspath'] = system_jars
config['javac']['classpath'] = javac_classpath config['javac']['classpath'] = javac_classpath
...@@ -1290,9 +1318,9 @@ def main(argv): ...@@ -1290,9 +1318,9 @@ def main(argv):
deps_info['javac_full_classpath'] = javac_full_classpath deps_info['javac_full_classpath'] = javac_full_classpath
deps_info['javac_full_interface_classpath'] = javac_full_interface_classpath deps_info['javac_full_interface_classpath'] = javac_full_interface_classpath
if options.type in ( if options.type in ('android_apk', 'dist_jar', 'java_binary', 'junit_binary',
'android_apk', 'dist_jar', 'java_binary', 'junit_binary'): 'android_app_bundle_module', 'android_app_bundle'):
deps_info['java_runtime_classpath'] = java_full_classpath deps_info['java_runtime_classpath'] = java_full_classpath
if options.type in ('android_apk', 'dist_jar'): if options.type in ('android_apk', 'dist_jar'):
all_interface_jars = [] all_interface_jars = []
...@@ -1304,7 +1332,7 @@ def main(argv): ...@@ -1304,7 +1332,7 @@ def main(argv):
'all_interface_jars': all_interface_jars, 'all_interface_jars': all_interface_jars,
} }
if options.type == 'android_apk': if is_apk_or_module_target:
manifest = AndroidManifest(options.android_manifest) manifest = AndroidManifest(options.android_manifest)
deps_info['package_name'] = manifest.GetPackageName() deps_info['package_name'] = manifest.GetPackageName()
if not options.tested_apk_config and manifest.GetInstrumentationElements(): if not options.tested_apk_config and manifest.GetInstrumentationElements():
......
...@@ -13,7 +13,8 @@ import("//build/config/sanitizers/sanitizers.gni") ...@@ -13,7 +13,8 @@ import("//build/config/sanitizers/sanitizers.gni")
assert(is_android) assert(is_android)
# These identify targets that have .build_config files (except for android_apk, # These identify targets that have .build_config files (except for android_apk,
# java_binary, resource_rewriter, since we never need to depend on these). # java_binary, resource_rewriter, android_app_bundle since we never need to
# depend on these).
_java_target_whitelist = [ _java_target_whitelist = [
"*:*_java", "*:*_java",
"*:*_javalib", "*:*_javalib",
...@@ -30,6 +31,7 @@ _java_target_whitelist = [ ...@@ -30,6 +31,7 @@ _java_target_whitelist = [
"*:*_resources", "*:*_resources",
"*:*_grd", "*:*_grd",
"*:*locale_paks", "*:*locale_paks",
"*_module",
# TODO(agrieve): Rename targets below to match above patterns. # TODO(agrieve): Rename targets below to match above patterns.
"*android_webview/glue:glue", "*android_webview/glue:glue",
...@@ -67,7 +69,8 @@ template("write_build_config") { ...@@ -67,7 +69,8 @@ template("write_build_config") {
# consider them in dependency chains. # consider them in dependency chains.
if (_type != "android_apk" && _type != "java_binary" && if (_type != "android_apk" && _type != "java_binary" &&
_type != "resource_rewriter" && _type != "dist_jar" && _type != "resource_rewriter" && _type != "dist_jar" &&
_type != "java_annotation_processor" && _type != "dist_aar") { _type != "java_annotation_processor" && _type != "dist_aar" &&
_type != "android_app_bundle") {
set_sources_assignment_filter(_java_target_whitelist) set_sources_assignment_filter(_java_target_whitelist)
_parent_invoker = invoker.invoker _parent_invoker = invoker.invoker
_target_label = _target_label =
...@@ -934,7 +937,7 @@ if (enable_java_templates) { ...@@ -934,7 +937,7 @@ if (enable_java_templates) {
"--output-path", "--output-path",
rebase_path(_output_jar_path, root_build_dir), rebase_path(_output_jar_path, root_build_dir),
"--classpath", "--classpath",
"@FileArg($_rebased_build_config:android:sdk_jars)", "@FileArg($_rebased_build_config:deps_info:proguard_classpath_jars)",
] ]
if (proguard_verbose) { if (proguard_verbose) {
args += [ "--verbose" ] args += [ "--verbose" ]
...@@ -2952,25 +2955,32 @@ if (enable_java_templates) { ...@@ -2952,25 +2955,32 @@ if (enable_java_templates) {
"secondary_abi_loadable_modules", "secondary_abi_loadable_modules",
"type", "type",
]) ])
if (type == "android_apk") { if (type == "android_apk" || type == "android_app_bundle_module") {
forward_variables_from( forward_variables_from(
invoker, invoker,
[ [
"android_manifest", "android_manifest",
"android_manifest_dep", "android_manifest_dep",
"apk_path",
"apk_under_test",
"extra_shared_libraries", "extra_shared_libraries",
"final_dex_path", "final_dex_path",
"incremental_allowed",
"incremental_apk_path",
"incremental_install_json_path",
"proto_resources_path",
"secondary_abi_shared_libraries_runtime_deps_file", "secondary_abi_shared_libraries_runtime_deps_file",
"shared_libraries_runtime_deps_file", "shared_libraries_runtime_deps_file",
"uncompress_shared_libraries", "uncompress_shared_libraries",
]) ])
} }
if (type == "android_apk") {
forward_variables_from(invoker,
[
"apk_path",
"apk_under_test",
"incremental_allowed",
"incremental_apk_path",
"incremental_install_json_path",
])
}
if (type == "android_app_bundle_module") {
forward_variables_from(invoker, [ "proto_resources_path" ])
}
build_config = _build_config build_config = _build_config
is_prebuilt = _is_prebuilt is_prebuilt = _is_prebuilt
possible_config_deps = _accumulated_deps possible_config_deps = _accumulated_deps
...@@ -3068,7 +3078,8 @@ if (enable_java_templates) { ...@@ -3068,7 +3078,8 @@ if (enable_java_templates) {
} }
if (_lint_enabled) { if (_lint_enabled) {
android_lint("${_main_target_name}__lint") { android_lint("${_main_target_name}__lint") {
if (invoker.type == "android_apk") { if (invoker.type == "android_apk" ||
invoker.type == "android_app_bundle_module") {
forward_variables_from(invoker, [ "android_manifest" ]) forward_variables_from(invoker, [ "android_manifest" ])
} else if (defined(_android_manifest_for_lint)) { } else if (defined(_android_manifest_for_lint)) {
android_manifest = _android_manifest_for_lint android_manifest = _android_manifest_for_lint
......
...@@ -1527,7 +1527,6 @@ if (enable_java_templates) { ...@@ -1527,7 +1527,6 @@ if (enable_java_templates) {
args = [ args = [
"--proguard-configs=@FileArg($_rebased_build_config:deps_info:proguard_all_configs)", "--proguard-configs=@FileArg($_rebased_build_config:deps_info:proguard_all_configs)",
"--input-paths=@FileArg($_rebased_build_config:deps_info:java_runtime_classpath)", "--input-paths=@FileArg($_rebased_build_config:deps_info:java_runtime_classpath)",
"--classpath=@FileArg($_rebased_build_config:deps_info:proguard_all_extra_jars)",
] ]
if (defined(invoker.proguard_config_exclusions)) { if (defined(invoker.proguard_config_exclusions)) {
_rebased_proguard_config_exclusions = _rebased_proguard_config_exclusions =
...@@ -2317,7 +2316,11 @@ if (enable_java_templates) { ...@@ -2317,7 +2316,11 @@ if (enable_java_templates) {
"secondary_abi_loadable_modules", "secondary_abi_loadable_modules",
"uncompress_shared_libraries", "uncompress_shared_libraries",
]) ])
type = "android_apk" if (_is_bundle_module) {
type = "android_app_bundle_module"
} else {
type = "android_apk"
}
main_target_name = _template_name main_target_name = _template_name
supports_android = true supports_android = true
requires_android = true requires_android = true
...@@ -2327,15 +2330,17 @@ if (enable_java_templates) { ...@@ -2327,15 +2330,17 @@ if (enable_java_templates) {
final_jar_path = _jar_path final_jar_path = _jar_path
dex_path = _lib_dex_path dex_path = _lib_dex_path
final_dex_path = _final_dex_path final_dex_path = _final_dex_path
apk_path = _final_apk_path
if (_is_bundle_module) { if (_is_bundle_module) {
proto_resources_path = _packaged_resources_path proto_resources_path = _packaged_resources_path
} }
incremental_allowed = _incremental_allowed if (!_is_bundle_module) {
incremental_apk_path = "${_final_apk_path_no_ext}_incremental.apk" apk_path = _final_apk_path
incremental_install_json_path = _incremental_install_json_path incremental_allowed = _incremental_allowed
incremental_apk_path = "${_final_apk_path_no_ext}_incremental.apk"
incremental_install_json_path = _incremental_install_json_path
}
proguard_enabled = _proguard_enabled proguard_enabled = _proguard_enabled
if (_proguard_enabled) { if (_proguard_enabled) {
...@@ -2401,7 +2406,6 @@ if (enable_java_templates) { ...@@ -2401,7 +2406,6 @@ if (enable_java_templates) {
args = [ args = [
"--proguard-configs=@FileArg($_rebased_build_config:deps_info:proguard_all_configs)", "--proguard-configs=@FileArg($_rebased_build_config:deps_info:proguard_all_configs)",
"--input-paths=@FileArg($_rebased_build_config:deps_info:java_runtime_classpath)", "--input-paths=@FileArg($_rebased_build_config:deps_info:java_runtime_classpath)",
"--classpath=@FileArg($_rebased_build_config:deps_info:proguard_all_extra_jars)",
] ]
if (defined(invoker.proguard_config_exclusions)) { if (defined(invoker.proguard_config_exclusions)) {
_rebased_proguard_config_exclusions = _rebased_proguard_config_exclusions =
...@@ -3662,6 +3666,19 @@ if (enable_java_templates) { ...@@ -3662,6 +3666,19 @@ if (enable_java_templates) {
_all_modules += invoker.extra_modules _all_modules += invoker.extra_modules
} }
# Make build config, which is required for synchronized proguarding.
_module_targets = []
foreach(_module, _all_modules) {
_module_targets += [ _module.module_target ]
}
_build_config = "$target_gen_dir/${target_name}.build_config"
_build_config_target = "${target_name}__build_config"
write_build_config(_build_config_target) {
type = "android_app_bundle"
possible_config_deps = _module_targets
build_config = _build_config
}
# Generate one module .zip file per APK. # Generate one module .zip file per APK.
_all_create_module_targets = [] _all_create_module_targets = []
_all_module_zip_paths = [] _all_module_zip_paths = []
...@@ -3760,7 +3777,7 @@ if (enable_java_templates) { ...@@ -3760,7 +3777,7 @@ if (enable_java_templates) {
outputs = [ outputs = [
_bundle_path, _bundle_path,
] ]
deps = _all_create_module_targets deps = _all_create_module_targets + [ ":$_build_config_target" ]
args = [ args = [
"--out-bundle=$_rebased_bundle_path", "--out-bundle=$_rebased_bundle_path",
"--module-zips=$_all_rebased_module_zip_paths", "--module-zips=$_all_rebased_module_zip_paths",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment