Add embedded_launcher: true to jni_generator

The jni_generator writes the path to the script into its output files.
When using a non-embedded-launcher soong python binary, soong will
extract the binary to a nondeterministic temporary directory before
running it. These two points together means that the output files
of jni_generator are non-deterministic.

Adding embedded_launcher: true causes all the python sources to be
precompiled as well, so we start getting syntax errors for code paths
that are still in python2 but we weren't running before. Fix those
syntax errors.

Test: Presubmits
Change-Id: I0a856f8cc98b11841c07bd6188d9722980428b5f
diff --git a/Android.bp b/Android.bp
index 8e00c48..7003244 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1205,6 +1205,11 @@
         "base/android/jni_generator/jni_generator.py",
         "build/**/*.py",
     ],
+    version: {
+        py3: {
+            embedded_launcher: true,
+        },
+    },
 }
 
 python_binary_host {
diff --git a/build/android/pylib/valgrind_tools.py b/build/android/pylib/valgrind_tools.py
index 3dc2488..30f09ad 100644
--- a/build/android/pylib/valgrind_tools.py
+++ b/build/android/pylib/valgrind_tools.py
@@ -106,8 +106,8 @@
   if ctor:
     return ctor(device)
   else:
-    print 'Unknown tool %s, available tools: %s' % (
-        tool_name, ', '.join(sorted(TOOL_REGISTRY.keys())))
+    print('Unknown tool %s, available tools: %s' % (
+        tool_name, ', '.join(sorted(TOOL_REGISTRY.keys()))))
     sys.exit(1)
 
 def PushFilesForTool(tool_name, device):
@@ -124,7 +124,7 @@
   if clazz:
     clazz.CopyFiles(device)
   else:
-    print 'Unknown tool %s, available tools: %s' % (
-        tool_name, ', '.join(sorted(TOOL_REGISTRY.keys())))
+    print('Unknown tool %s, available tools: %s' % (
+        tool_name, ', '.join(sorted(TOOL_REGISTRY.keys()))))
     sys.exit(1)
 
diff --git a/build/apply_locales.py b/build/apply_locales.py
index 6af7280..99d73d3 100755
--- a/build/apply_locales.py
+++ b/build/apply_locales.py
@@ -20,7 +20,7 @@
   (options, arglist) = parser.parse_args(argv)
 
   if len(arglist) < 3:
-    print 'ERROR: need string and list of locales'
+    print('ERROR: need string and list of locales')
     return 1
 
   str_template = arglist[1]
@@ -39,7 +39,7 @@
 
   # Quote each element so filename spaces don't mess up GYP's attempt to parse
   # it into a list.
-  print ' '.join(["'%s'" % x for x in results])
+  print(' '.join(["'%s'" % x for x in results]))
 
 if __name__ == '__main__':
   sys.exit(main(sys.argv))
diff --git a/build/check_gn_headers.py b/build/check_gn_headers.py
index 42ea80f..17cfe56 100755
--- a/build/check_gn_headers.py
+++ b/build/check_gn_headers.py
@@ -135,7 +135,7 @@
     gclient_out = subprocess.check_output([
         os.path.join(DEPOT_TOOLS_DIR, gclient_exe),
         'recurse', '--no-progress', '-j1',
-        'python', '-c', 'import os;print os.environ["GCLIENT_DEP_PATH"]'],
+        'python', '-c', 'import os;print(os.environ["GCLIENT_DEP_PATH"])'],
         universal_newlines=True)
     for i in gclient_out.split('\n'):
       if i.startswith('src/'):
@@ -152,7 +152,7 @@
     out = subprocess.check_output(cmd)
     return 'no work to do.' in out
   except Exception as e:
-    print e
+    print(e)
     return False
 
 def ParseWhiteList(whitelist):
@@ -211,7 +211,7 @@
       # Assume running on the bots. Silently skip this step.
       # This is possible because "analyze" step can be wrong due to
       # underspecified header files. See crbug.com/725877
-      print dirty_msg
+      print(dirty_msg)
       DumpJson([])
       return 0
     else:
@@ -250,7 +250,7 @@
   if deps_err:
     PrintError(deps_err)
   if len(GetNonExistingFiles(d)) > 0:
-    print 'Non-existing files in ninja deps:', GetNonExistingFiles(d)
+    print('Non-existing files in ninja deps:', GetNonExistingFiles(d))
     PrintError('Found non-existing files in ninja deps. You should ' +
                'build all in OUT_DIR.')
   if len(d) == 0:
@@ -272,30 +272,30 @@
     return 0
 
   if len(missing) > 0:
-    print '\nThe following files should be included in gn files:'
+    print('\nThe following files should be included in gn files:')
     for i in missing:
-      print i
+      print(i)
 
   if len(nonexisting) > 0:
-    print '\nThe following non-existing files should be removed from gn files:'
+    print('\nThe following non-existing files should be removed from gn files:')
     for i in nonexisting:
-      print i
+      print(i)
 
   if args.verbose:
     # Only get detailed obj dependency here since it is slower.
     GetHeadersFromNinja(args.out_dir, False, d_q)
     d, d_err = d_q.get()
-    print '\nDetailed dependency info:'
+    print('\nDetailed dependency info:')
     for f in missing:
-      print f
+      print(f)
       for cc in d[f]:
-        print '  ', cc
+        print('  ', cc)
 
-    print '\nMissing headers sorted by number of affected object files:'
+    print('\nMissing headers sorted by number of affected object files:')
     count = {k: len(v) for (k, v) in d.items()}
     for f in sorted(count, key=count.get, reverse=True):
       if f in missing:
-        print count[f], f
+        print(count[f], f)
 
   return 1
 
diff --git a/build/check_return_value.py b/build/check_return_value.py
index c659d1e..0ca207b 100755
--- a/build/check_return_value.py
+++ b/build/check_return_value.py
@@ -12,6 +12,6 @@
 
 devnull = open(os.devnull, 'wb')
 if not subprocess.call(sys.argv[1:], stdout=devnull, stderr=devnull):
-  print 1
+  print(1)
 else:
-  print 0
+  print(0)
diff --git a/build/detect_host_arch.py b/build/detect_host_arch.py
index 0e491bc..d5bebdf 100755
--- a/build/detect_host_arch.py
+++ b/build/detect_host_arch.py
@@ -48,4 +48,4 @@
   return HostArch()
 
 if __name__ == '__main__':
-  print DoMain([])
+  print(DoMain([]))
diff --git a/build/extract_from_cab.py b/build/extract_from_cab.py
index 080370c..4a273b2 100755
--- a/build/extract_from_cab.py
+++ b/build/extract_from_cab.py
@@ -17,12 +17,12 @@
   out, _ = popen.communicate()
   if popen.returncode:
     # expand emits errors to stdout, so if we fail, then print that out.
-    print out
+    print(out)
   return popen.returncode
 
 def main():
   if len(sys.argv) != 4:
-    print 'Usage: extract_from_cab.py cab_path archived_file output_dir'
+    print('Usage: extract_from_cab.py cab_path archived_file output_dir')
     return 1
 
   [cab_path, archived_file, output_dir] = sys.argv[1:]
diff --git a/build/find_depot_tools.py b/build/find_depot_tools.py
index 5c496e7..c42a2c1 100755
--- a/build/find_depot_tools.py
+++ b/build/find_depot_tools.py
@@ -53,7 +53,7 @@
       return i
     previous_dir = root_dir
     root_dir = os.path.dirname(root_dir)
-  print >> sys.stderr, 'Failed to find depot_tools'
+  print('Failed to find depot_tools', file=sys.stderr)
   return None
 
 DEPOT_TOOLS_PATH = add_depot_tools_to_path()
@@ -65,7 +65,7 @@
 def main():
   if DEPOT_TOOLS_PATH is None:
     return 1
-  print DEPOT_TOOLS_PATH
+  print(DEPOT_TOOLS_PATH)
   return 0
 
 
diff --git a/build/fix_gn_headers.py b/build/fix_gn_headers.py
index 01ff764..65b93f6 100755
--- a/build/fix_gn_headers.py
+++ b/build/fix_gn_headers.py
@@ -39,7 +39,7 @@
       continue
     if lines[linenr - 2] == new:
       continue
-    print '    ', gnfile, linenr, new
+    print('    ', gnfile, linenr, new)
     matches.append((gnfile, linenr, new))
   return matches
 
@@ -59,7 +59,7 @@
     if not (filename.endswith('.h') or filename.endswith('.hh')):
       continue
     basename = os.path.basename(filename)
-    print filename
+    print(filename)
     cc = r'\b' + os.path.splitext(basename)[0] + r'\.(cc|cpp|mm)\b'
     out, returncode = GitGrep('(/|")' + cc + '"')
     if returncode != 0 or not out:
@@ -71,9 +71,9 @@
     if len(matches) == 0:
       continue
     if len(matches) > 1:
-      print '\n[WARNING] Ambiguous matching for', filename
+      print('\n[WARNING] Ambiguous matching for', filename)
       for i in enumerate(matches, 1):
-        print '%d: %s' % (i[0], i[1])
+        print('%d: %s' % (i[0], i[1]))
       print
       if skip_ambiguous:
         continue
@@ -86,7 +86,7 @@
 
     for match in matches:
       gnfile, linenr, new = match
-      print '  ', gnfile, linenr, new
+      print('  ', gnfile, linenr, new)
       edits.setdefault(gnfile, {})[linenr] = new
 
   for gnfile in edits:
@@ -111,7 +111,7 @@
   """
   for filename in headers:
     filename = filename.strip()
-    print filename
+    print(filename)
     dirname = os.path.dirname(filename)
     while not os.path.exists(os.path.join(dirname, 'BUILD.gn')):
       dirname = os.path.dirname(dirname)
@@ -121,12 +121,12 @@
     lines = open(gnfile).read().splitlines()
     matched = [i for i, l in enumerate(lines) if ' sources = [' in l]
     if skip_ambiguous and len(matched) > 1:
-      print '[WARNING] Multiple sources in', gnfile
+      print('[WARNING] Multiple sources in', gnfile)
       continue
 
     if len(matched) < 1:
       continue
-    print '  ', gnfile, rel
+    print('  ', gnfile, rel)
     index = matched[0]
     lines.insert(index + 1, '"%s",' % rel)
     open(gnfile, 'w').write('\n'.join(lines) + '\n')
@@ -144,18 +144,18 @@
     if not (filename.endswith('.h') or filename.endswith('.hh')):
       continue
     basename = os.path.basename(filename)
-    print filename
+    print(filename)
     out, returncode = GitGrep('(/|")' + basename + '"')
     if returncode != 0 or not out:
       unhandled.append(filename)
-      print '  Not found'
+      print('  Not found')
       continue
 
     grep_lines = out.splitlines()
     matches = []
     for line in grep_lines:
       gnfile, linenr, contents = line.split(':')
-      print '    ', gnfile, linenr, contents
+      print('    ', gnfile, linenr, contents)
       linenr = int(linenr)
       lines = open(gnfile).read().splitlines()
       assert contents in lines[linenr - 1]
@@ -164,9 +164,9 @@
     if len(matches) == 0:
       continue
     if len(matches) > 1:
-      print '\n[WARNING] Ambiguous matching for', filename
+      print('\n[WARNING] Ambiguous matching for', filename)
       for i in enumerate(matches, 1):
-        print '%d: %s' % (i[0], i[1])
+        print('%d: %s' % (i[0], i[1]))
       print
       if skip_ambiguous:
         continue
@@ -179,7 +179,7 @@
 
     for match in matches:
       gnfile, linenr, contents = match
-      print '  ', gnfile, linenr, contents
+      print('  ', gnfile, linenr, contents)
       edits.setdefault(gnfile, set()).add(linenr)
 
   for gnfile in edits:
diff --git a/build/get_landmines.py b/build/get_landmines.py
index 8a655e3..2a1feb6 100755
--- a/build/get_landmines.py
+++ b/build/get_landmines.py
@@ -37,41 +37,41 @@
   # usually less troublesome alternatives.
 
   if host_os() == 'win':
-    print 'Compile on cc_unittests fails due to symbols removed in r185063.'
+    print('Compile on cc_unittests fails due to symbols removed in r185063.')
   if host_os() == 'linux':
-    print 'Builders switching from make to ninja will clobber on this.'
+    print('Builders switching from make to ninja will clobber on this.')
   if host_os() == 'mac':
-    print 'Switching from bundle to unbundled dylib (issue 14743002).'
+    print('Switching from bundle to unbundled dylib (issue 14743002).')
   if host_os() in ('win', 'mac'):
-    print ('Improper dependency for create_nmf.py broke in r240802, '
+    print('Improper dependency for create_nmf.py broke in r240802, '
            'fixed in r240860.')
   if host_os() == 'win':
-    print 'Switch to VS2015 Update 3, 14393 SDK'
-  print 'Need to clobber everything due to an IDL change in r154579 (blink)'
-  print 'Need to clobber everything due to gen file moves in r175513 (Blink)'
-  print 'Clobber to get rid of obselete test plugin after r248358'
-  print 'Clobber to rebuild GN files for V8'
-  print 'Clobber to get rid of stale generated mojom.h files'
-  print 'Need to clobber everything due to build_nexe change in nacl r13424'
-  print '[chromium-dev] PSA: clobber build needed for IDR_INSPECTOR_* compil...'
-  print 'blink_resources.grd changed: crbug.com/400860'
-  print 'ninja dependency cycle: crbug.com/408192'
-  print 'Clobber to fix missing NaCl gyp dependencies (crbug.com/427427).'
-  print 'Another clobber for missing NaCl gyp deps (crbug.com/427427).'
-  print 'Clobber to fix GN not picking up increased ID range (crbug.com/444902)'
-  print 'Remove NaCl toolchains from the output dir (crbug.com/456902)'
+    print('Switch to VS2015 Update 3, 14393 SDK')
+  print('Need to clobber everything due to an IDL change in r154579 (blink)')
+  print('Need to clobber everything due to gen file moves in r175513 (Blink)')
+  print('Clobber to get rid of obselete test plugin after r248358')
+  print('Clobber to rebuild GN files for V8')
+  print('Clobber to get rid of stale generated mojom.h files')
+  print('Need to clobber everything due to build_nexe change in nacl r13424')
+  print('[chromium-dev] PSA: clobber build needed for IDR_INSPECTOR_* compil...')
+  print('blink_resources.grd changed: crbug.com/400860')
+  print('ninja dependency cycle: crbug.com/408192')
+  print('Clobber to fix missing NaCl gyp dependencies (crbug.com/427427).')
+  print('Another clobber for missing NaCl gyp deps (crbug.com/427427).')
+  print('Clobber to fix GN not picking up increased ID range (crbug.com/444902)')
+  print('Remove NaCl toolchains from the output dir (crbug.com/456902)')
   if host_os() == 'win':
-    print 'Clobber to delete stale generated files (crbug.com/510086)'
+    print('Clobber to delete stale generated files (crbug.com/510086)')
   if host_os() == 'mac':
-    print 'Clobber to get rid of evil libsqlite3.dylib (crbug.com/526208)'
+    print('Clobber to get rid of evil libsqlite3.dylib (crbug.com/526208)')
   if host_os() == 'mac':
-    print 'Clobber to remove libsystem.dylib. See crbug.com/620075'
+    print('Clobber to remove libsystem.dylib. See crbug.com/620075')
   if host_os() == 'mac':
-    print 'Clobber to get past mojo gen build error (crbug.com/679607)'
+    print('Clobber to get past mojo gen build error (crbug.com/679607)')
   if host_os() == 'win':
-    print 'Clobber Windows to fix strange PCH-not-rebuilt errors.'
-  print 'CLobber all to fix GN breakage (crbug.com/736215)'
-  print 'The Great Blink mv for source files (crbug.com/768828)'
+    print('Clobber Windows to fix strange PCH-not-rebuilt errors.')
+  print('CLobber all to fix GN breakage (crbug.com/736215)')
+  print('The Great Blink mv for source files (crbug.com/768828)')
 
 def main():
   print_landmines()
diff --git a/build/gn_run_binary.py b/build/gn_run_binary.py
index d7f7165..02e4475 100644
--- a/build/gn_run_binary.py
+++ b/build/gn_run_binary.py
@@ -25,7 +25,7 @@
     # Windows error codes such as 0xC0000005 and 0xC0000409 are much easier to
     # recognize and differentiate in hex. In order to print them as unsigned
     # hex we need to add 4 Gig to them.
-    print '%s failed with exit code 0x%08X' % (sys.argv[1], ret + (1 << 32))
+    print('%s failed with exit code 0x%08X' % (sys.argv[1], ret + (1 << 32)))
   else:
-    print '%s failed with exit code %d' % (sys.argv[1], ret)
+    print('%s failed with exit code %d' % (sys.argv[1], ret))
 sys.exit(ret)
diff --git a/build/gyp_chromium.py b/build/gyp_chromium.py
index ab2e470..fe5d4b7 100644
--- a/build/gyp_chromium.py
+++ b/build/gyp_chromium.py
@@ -56,7 +56,7 @@
 def main():
   gyp_environment.SetEnvironment()
 
-  print 'Updating projects from gyp files...'
+  print('Updating projects from gyp files...')
   sys.stdout.flush()
   sys.exit(gyp.main(sys.argv[1:] + [
       '--check',
diff --git a/build/gyp_helper.py b/build/gyp_helper.py
index c840f2d..9543ed3 100644
--- a/build/gyp_helper.py
+++ b/build/gyp_helper.py
@@ -19,7 +19,7 @@
     file_contents = f.read()
   try:
     file_data = eval(file_contents, {'__builtins__': None}, None)
-  except SyntaxError, e:
+  except SyntaxError as e:
     e.filename = os.path.abspath(file_path)
     raise
   supported_vars = (
@@ -50,12 +50,12 @@
           behavior = 'merges with, and individual components override,'
         else:
           result = os.environ[var]
-        print 'INFO: Environment value for "%s" %s value in %s' % (
+        print('INFO: Environment value for "%s" %s value in %s' % (
             var, behavior, os.path.abspath(file_path)
-        )
+        ))
         string_padding = max(len(var), len(file_path), len('result'))
-        print '      %s: %s' % (var.rjust(string_padding), os.environ[var])
-        print '      %s: %s' % (file_path.rjust(string_padding), file_val)
+        print('      %s: %s' % (var.rjust(string_padding), os.environ[var]))
+        print('      %s: %s' % (file_path.rjust(string_padding), file_val))
         os.environ[var] = result
       else:
         os.environ[var] = file_val
diff --git a/build/gypi_to_gn.py b/build/gypi_to_gn.py
index 2a3a72a..407d6bb 100644
--- a/build/gypi_to_gn.py
+++ b/build/gypi_to_gn.py
@@ -100,10 +100,10 @@
   file_string = open(path).read()
   try:
     file_data = eval(file_string, {'__builtins__': None}, None)
-  except SyntaxError, e:
+  except SyntaxError as e:
     e.filename = path
     raise
-  except Exception, e:
+  except Exception as e:
     raise Exception("Unexpected error while reading %s: %s" % (path, str(e)))
 
   assert isinstance(file_data, dict), "%s does not eval to a dictionary" % path
@@ -182,11 +182,11 @@
       data[key[:-1]] = data[key]
       del data[key]
 
-  print gn_helpers.ToGNString(data)
+  print(gn_helpers.ToGNString(data))
 
 if __name__ == '__main__':
   try:
     main()
-  except Exception, e:
-    print str(e)
+  except Exception as e:
+    print(str(e))
     sys.exit(1)
diff --git a/build/protoc_java.py b/build/protoc_java.py
index 2addb82..d7df8f4 100755
--- a/build/protoc_java.py
+++ b/build/protoc_java.py
@@ -39,7 +39,7 @@
 
   build_utils.CheckOptions(options, parser, ['protoc', 'proto_path'])
   if not options.java_out_dir and not options.srcjar:
-    print 'One of --java-out-dir or --srcjar must be specified.'
+    print('One of --java-out-dir or --srcjar must be specified.')
     return 1
 
   with build_utils.TempDir() as temp_dir:
diff --git a/build/run_swarming_xcode_install.py b/build/run_swarming_xcode_install.py
index a731c1b..f5b4254 100755
--- a/build/run_swarming_xcode_install.py
+++ b/build/run_swarming_xcode_install.py
@@ -39,7 +39,7 @@
   script_dir = os.path.dirname(os.path.abspath(__file__))
   tmp_dir = tempfile.mkdtemp(prefix='swarming_xcode')
   try:
-    print 'Making isolate.'
+    print('Making isolate.')
     shutil.copyfile(os.path.join(script_dir, 'swarming_xcode_install.py'),
                     os.path.join(tmp_dir, 'swarming_xcode_install.py'))
     shutil.copyfile(os.path.join(script_dir, 'mac_toolchain.py'),
@@ -52,7 +52,7 @@
     ]
     isolate_hash = subprocess.check_output(cmd).split()[0]
 
-    print 'Running swarming_xcode_install.'
+    print('Running swarming_xcode_install.')
     # TODO(crbug.com/765361): The dimensions below should be updated once
     # swarming for iOS is fleshed out, likely removing xcode_version 9 and
     # adding different dimensions.
@@ -70,7 +70,7 @@
       'python', 'swarming_xcode_install.py',
     ]
     subprocess.check_call(cmd)
-    print 'All tasks completed.'
+    print('All tasks completed.')
 
   finally:
     shutil.rmtree(tmp_dir)
diff --git a/build/swarming_xcode_install.py b/build/swarming_xcode_install.py
index 7764aa5..d0c183d 100755
--- a/build/swarming_xcode_install.py
+++ b/build/swarming_xcode_install.py
@@ -30,12 +30,12 @@
     found_version = \
         subprocess.Popen(cmd, env=env, stdout=subprocess.PIPE).communicate()[0]
     if VERSION in found_version:
-      print "Xcode %s already installed" % VERSION
+      print("Xcode %s already installed" % VERSION)
       sys.exit(0)
 
   # Confirm old dir is there first.
   if not os.path.exists(REMOVE_DIR):
-    print "Failing early since %s isn't there." % REMOVE_DIR
+    print("Failing early since %s isn't there." % REMOVE_DIR)
     sys.exit(1)
 
   # Download Xcode.
diff --git a/build/symlink.py b/build/symlink.py
index 5a261dc..4fc6cc4 100755
--- a/build/symlink.py
+++ b/build/symlink.py
@@ -40,7 +40,7 @@
       continue
     try:
       os.symlink(s, t)
-    except OSError, e:
+    except OSError as e:
       if e.errno == errno.EEXIST and options.force:
         if os.path.isdir(t):
           shutil.rmtree(t, ignore_errors=True)
diff --git a/build/vs_toolchain.py b/build/vs_toolchain.py
index 83847f4..dc1e0f0 100755
--- a/build/vs_toolchain.py
+++ b/build/vs_toolchain.py
@@ -164,7 +164,7 @@
       (not os.path.isfile(target) or
        abs(os.stat(target).st_mtime - os.stat(source).st_mtime) >= 0.01)):
     if verbose:
-      print 'Copying %s to %s...' % (source, target)
+      print('Copying %s to %s...' % (source, target))
     if os.path.exists(target):
       # Make the file writable so that we can delete it now, and keep it
       # readable.
@@ -362,7 +362,7 @@
   information required to pass to gyp which we use in |GetToolchainDir()|.
   """
   if force != False and force != '--force':
-    print >>sys.stderr, 'Unknown parameter "%s"' % force
+    print('Unknown parameter "%s"' % force, file=sys.stderr)
     return 1
   if force == '--force' or os.path.exists(json_data_file):
     force = True
@@ -442,7 +442,7 @@
   runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs()
   win_sdk_dir = SetEnvironmentAndGetSDKDir()
 
-  print '''vs_path = %s
+  print('''vs_path = %s
 sdk_path = %s
 vs_version = %s
 wdk_dir = %s
@@ -452,7 +452,7 @@
       ToGNString(win_sdk_dir),
       ToGNString(GetVisualStudioVersion()),
       ToGNString(NormalizePath(os.environ.get('WDK_DIR', ''))),
-      ToGNString(os.path.pathsep.join(runtime_dll_dirs or ['None'])))
+      ToGNString(os.path.pathsep.join(runtime_dll_dirs or ['None']))))
 
 
 def main():
@@ -462,7 +462,7 @@
       'copy_dlls': CopyDlls,
   }
   if len(sys.argv) < 2 or sys.argv[1] not in commands:
-    print >>sys.stderr, 'Expected one of: %s' % ', '.join(commands)
+    print('Expected one of: %s' % ', '.join(commands), file=sys.stderr)
     return 1
   return commands[sys.argv[1]](*sys.argv[2:])