Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Functions | Variables
create_apk Namespace Reference

Classes

class  ChDir
 
class  RemoveFiles
 
class  SkQP_Build_Options
 

Functions

 print_cmd (cmd, o)
 
 check_call (cmd, **kwargs)
 
 find_name (searchpath, filename)
 
 check_ninja ()
 
 remove (p)
 
 makedirs (dst)
 
 make_symlinked_subdir (target, working_dir)
 
 accept_android_license (android_home)
 
 create_apk_impl (opts)
 
 create_apk (opts)
 
 main ()
 

Variables

dict skia_to_android_arch_name_map
 

Detailed Description

This script can be run with no arguments, in which case it will produce an
APK with native libraries for all four architectures: arm, arm64, x86, and
x64.  You can instead list the architectures you want as arguments to this
script.  For example:

    python create_apk.py arm x86

The environment variables ANDROID_NDK_HOME and ANDROID_HOME must be set to
the locations of the Android NDK and SDK.

Additionally, `ninja` should be in your path.

It assumes that the source tree is in the desired state, e.g. by having
run 'python tools/git-sync-deps' in the root of the skia checkout.

We also assume that the 'resources' directory has been copied to
'platform_tools/android/apps/skqp/src/main/assets', and the
'tools/skqp/download_model' script has been run.

Also:
  * If the environment variable SKQP_BUILD_DIR is set, many of the
    intermediate build objects will be placed here.
  * If the environment variable SKQP_OUTPUT_DIR is set, the final APK
    will be placed in this directory.
  * If the environment variable SKQP_DEBUG is set, Skia will be compiled
    in debug mode.

Function Documentation

◆ accept_android_license()

create_apk.accept_android_license (   android_home)

Definition at line 104 of file create_apk.py.

104def accept_android_license(android_home):
105 proc = subprocess.Popen(
106 [android_home + '/tools/bin/sdkmanager', '--licenses'],
107 stdin=subprocess.PIPE)
108 while proc.poll() is None:
109 proc.stdin.write('y\n')
110 time.sleep(1)
111
112# pylint: disable=bad-whitespace

◆ check_call()

create_apk.check_call (   cmd,
**  kwargs 
)

Definition at line 56 of file create_apk.py.

56def check_call(cmd, **kwargs):
57 print_cmd(cmd, sys.stdout)
58 return subprocess.check_call(cmd, **kwargs)
59

◆ check_ninja()

create_apk.check_ninja ( )

Definition at line 65 of file create_apk.py.

65def check_ninja():
66 with open(os.devnull, 'w') as devnull:
67 return subprocess.call(['ninja', '--version'],
68 stdout=devnull, stderr=devnull) == 0
69

◆ create_apk()

create_apk.create_apk (   opts)

Definition at line 190 of file create_apk.py.

190def create_apk(opts):
191 skia_dir = os.path.abspath(os.path.dirname(__file__) + '/../..')
192 assert os.path.exists(skia_dir)
193 with ChDir(skia_dir):
194 create_apk_impl(opts)
195

◆ create_apk_impl()

create_apk.create_apk_impl (   opts)

Definition at line 118 of file create_apk.py.

118def create_apk_impl(opts):
119 build_dir, final_output_dir = opts.build_dir, opts.final_output_dir
120
121 assert os.path.exists('bin/gn') # Did you `tools/git-syc-deps`?
122
123 for d in [build_dir, final_output_dir]:
124 makedirs(d)
125
126 apps_dir = 'platform_tools/android/apps'
127 app = 'skqp'
128 lib = 'lib%s_jni.so' % app
129
130 # These are the locations in the tree where the gradle needs or will create
131 # not-checked-in files. Treat them specially to keep the tree clean.
132 remove(build_dir + '/libs')
133 build_paths = [apps_dir + '/.gradle',
134 apps_dir + '/' + app + '/build',
135 apps_dir + '/' + app + '/src/main/libs']
136 for path in build_paths:
137 remove(path)
138 try:
139 make_symlinked_subdir(path, build_dir)
140 except OSError:
141 sys.stderr.write('failed to create symlink "%s"\n' % path)
142
143 lib_dir = '%s/%s/src/main/libs' % (apps_dir, app)
144 apk_build_dir = '%s/%s/build/outputs/apk' % (apps_dir, app)
145 for d in [lib_dir, apk_build_dir]:
146 shutil.rmtree(d, True) # force rebuild
147
148 with RemoveFiles(*build_paths):
149 for arch in opts.architectures:
150 build = os.path.join(build_dir, arch)
151 gn_args = opts.gn_args(arch)
152 args = ' '.join('%s=%s' % (k, v) for k, v in gn_args.items())
153 check_call(['bin/gn', 'gen', build, '--args=' + args])
154 try:
155 check_call(['ninja', '-C', build, lib])
156 except subprocess.CalledProcessError:
157 check_call(['ninja', '-C', build, '-t', 'clean'])
158 check_call(['ninja', '-C', build, lib])
159 dst = '%s/%s' % (lib_dir, skia_to_android_arch_name_map[arch])
160 makedirs(dst)
161 shutil.copy(os.path.join(build, lib), dst)
162
163 accept_android_license(opts.android_home)
164 env_copy = os.environ.copy()
165 env_copy['ANDROID_HOME'] = opts.android_home
166 env_copy['ANDROID_NDK_HOME'] = opts.android_ndk
167 # Why does gradlew need to be called from this directory?
168 check_call(['apps/gradlew', '-p' 'apps/' + app,
169 '-P', 'suppressNativeBuild',
170 ':%s:assembleUniversalDebug' % app],
171 env=env_copy, cwd='platform_tools/android')
172
173 apk_name = app + "-universal-debug.apk"
174
175 apk_list = list(find_name(apk_build_dir, apk_name))
176 assert len(apk_list) == 1
177
178 out = os.path.join(final_output_dir, apk_name)
179 shutil.move(apk_list[0], out)
180 sys.stdout.write(out + '\n')
181
182 arches = '_'.join(sorted(opts.architectures))
183 copy = os.path.join(final_output_dir, "%s-%s-debug.apk" % (app, arches))
184 shutil.copyfile(out, copy)
185 sys.stdout.write(copy + '\n')
186
187 sys.stdout.write('* * * COMPLETE * * *\n\n')
188
189

◆ find_name()

create_apk.find_name (   searchpath,
  filename 
)

Definition at line 60 of file create_apk.py.

60def find_name(searchpath, filename):
61 for dirpath, _, filenames in os.walk(searchpath):
62 if filename in filenames:
63 yield os.path.join(dirpath, filename)
64

◆ main()

create_apk.main ( )

Definition at line 232 of file create_apk.py.

232def main():
233 options = SkQP_Build_Options()
234 if options.error:
235 sys.stderr.write(options.error + __doc__)
236 sys.exit(1)
237 options.write(sys.stdout)
238 create_apk(options)
239
Definition main.py:1

◆ make_symlinked_subdir()

create_apk.make_symlinked_subdir (   target,
  working_dir 
)

Definition at line 99 of file create_apk.py.

99def make_symlinked_subdir(target, working_dir):
100 newdir = os.path.join(working_dir, os.path.basename(target))
101 makedirs(newdir)
102 os.symlink(os.path.relpath(newdir, os.path.dirname(target)), target)
103

◆ makedirs()

create_apk.makedirs (   dst)

Definition at line 77 of file create_apk.py.

77def makedirs(dst):
78 if not os.path.exists(dst):
79 os.makedirs(dst)
80

◆ print_cmd()

create_apk.print_cmd (   cmd,
  o 
)

Definition at line 45 of file create_apk.py.

45def print_cmd(cmd, o):
46 m = re.compile('[^A-Za-z0-9_./-]')
47 o.write('+ ')
48 for c in cmd:
49 if m.search(c) is not None:
50 o.write(repr(c) + ' ')
51 else:
52 o.write(c + ' ')
53 o.write('\n')
54 o.flush()
55

◆ remove()

create_apk.remove (   p)

Definition at line 70 of file create_apk.py.

70def remove(p):
71 if not os.path.islink(p) and os.path.isdir(p):
72 shutil.rmtree(p)
73 elif os.path.lexists(p):
74 os.remove(p)
75 assert not os.path.exists(p)
76

Variable Documentation

◆ skia_to_android_arch_name_map

dict create_apk.skia_to_android_arch_name_map
Initial value:
1= {'arm' : 'armeabi-v7a',
2 'arm64': 'arm64-v8a' ,
3 'x86' : 'x86' ,
4 'x64' : 'x86_64' }

Definition at line 113 of file create_apk.py.