Add copyright banner to scripts.
[platform/upstream/VK-GL-CTS.git] / android / scripts / build.py
1 # -*- coding: utf-8 -*-
2
3 #-------------------------------------------------------------------------
4 # drawElements Quality Program utilities
5 # --------------------------------------
6 #
7 # Copyright 2015 The Android Open Source Project
8 #
9 # Licensed under the Apache License, Version 2.0 (the "License");
10 # you may not use this file except in compliance with the License.
11 # You may obtain a copy of the License at
12 #
13 #      http://www.apache.org/licenses/LICENSE-2.0
14 #
15 # Unless required by applicable law or agreed to in writing, software
16 # distributed under the License is distributed on an "AS IS" BASIS,
17 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 # See the License for the specific language governing permissions and
19 # limitations under the License.
20 #
21 #-------------------------------------------------------------------------
22
23 import os
24 import re
25 import sys
26 import shutil
27 import argparse
28
29 import common
30
31 def getStoreKeyPasswords (filename):
32         f                       = open(filename)
33         storepass       = None
34         keypass         = None
35         for line in f:
36                 m = re.search('([a-z]+)\s*\=\s*"([^"]+)"', line)
37                 if m != None:
38                         if m.group(1) == "storepass":
39                                 storepass = m.group(2)
40                         elif m.group(1) == "keypass":
41                                 keypass = m.group(2)
42         f.close()
43         if storepass == None or keypass == None:
44                 common.die("Could not read signing key passwords")
45         return (storepass, keypass)
46
47 def getNativeBuildDir (buildRoot, nativeLib, buildType):
48         buildName = "%s-%d-%s" % (buildType.lower(), nativeLib.apiVersion, nativeLib.abiVersion)
49         return os.path.normpath(os.path.join(buildRoot, "native", buildName))
50
51 def getAssetsDir (buildRoot, nativeLib, buildType):
52         return os.path.join(getNativeBuildDir(buildRoot, nativeLib, buildType), "assets")
53
54 def getPrebuiltsDirName (abiName):
55         PREBUILT_DIRS = {
56                         'x86':                  'android-x86',
57                         'armeabi-v7a':  'android-arm',
58                         'arm64-v8a':    'android-arm64'
59                 }
60
61         if not abiName in PREBUILT_DIRS:
62                 raise Exception("Unknown ABI %s, don't know where prebuilts are" % abiName)
63
64         return PREBUILT_DIRS[abiName]
65
66 def buildNative (buildRoot, libTargetDir, nativeLib, buildType):
67         deqpDir         = os.path.normpath(os.path.join(common.ANDROID_DIR, ".."))
68         buildDir        = getNativeBuildDir(buildRoot, nativeLib, buildType)
69         libsDir         = os.path.join(libTargetDir, nativeLib.abiVersion)
70         srcLibFile      = os.path.join(buildDir, common.NATIVE_LIB_NAME)
71         dstLibFile      = os.path.join(libsDir, common.NATIVE_LIB_NAME)
72
73         # Make build directory if necessary
74         if not os.path.exists(buildDir):
75                 os.makedirs(buildDir)
76                 toolchainFile = '%s/framework/delibs/cmake/toolchain-android-%s.cmake' % (deqpDir, common.ANDROID_NDK_TOOLCHAIN_VERSION)
77                 common.execArgsInDirectory([
78                                 'cmake',
79                                 '-G%s' % common.CMAKE_GENERATOR,
80                                 '-DCMAKE_TOOLCHAIN_FILE=%s' % toolchainFile,
81                                 '-DANDROID_NDK_HOST_OS=%s' % common.ANDROID_NDK_HOST_OS,
82                                 '-DANDROID_NDK_PATH=%s' % common.ANDROID_NDK_PATH,
83                                 '-DANDROID_ABI=%s' % nativeLib.abiVersion,
84                                 '-DDE_ANDROID_API=%s' % nativeLib.apiVersion,
85                                 '-DCMAKE_BUILD_TYPE=%s' % buildType,
86                                 '-DDEQP_TARGET=android',
87                                 deqpDir
88                         ], buildDir)
89
90         common.execArgsInDirectory(['cmake', '--build', '.'] + common.EXTRA_BUILD_ARGS, buildDir)
91
92         if not os.path.exists(libsDir):
93                 os.makedirs(libsDir)
94
95         shutil.copyfile(srcLibFile, dstLibFile)
96
97         # Copy gdbserver for debugging
98         if buildType.lower() == "debug":
99                 srcGdbserverPath = os.path.join(common.ANDROID_NDK_PATH,
100                                                                                 'prebuilt',
101                                                                                 getPrebuiltsDirName(nativeLib.abiVersion),
102                                                                                 'gdbserver',
103                                                                                 'gdbserver')
104                 dstGdbserverPath = os.path.join(libsDir, 'gdbserver')
105                 shutil.copyfile(srcGdbserverPath, dstGdbserverPath)
106         else:
107                 assert not os.path.exists(os.path.join(libsDir, "gdbserver"))
108
109 def buildApp (buildRoot, isRelease, javaApi):
110         appDir  = os.path.join(buildRoot, "package")
111
112         # Set up app
113         os.chdir(appDir)
114
115         manifestSrcPath = os.path.normpath(os.path.join(common.ANDROID_DIR, "package", "AndroidManifest.xml"))
116         manifestDstPath = os.path.normpath(os.path.join(appDir, "AndroidManifest.xml"))
117
118         # Build dir can be the Android dir, in which case the copy is not needed.
119         if manifestSrcPath != manifestDstPath:
120                 shutil.copy(manifestSrcPath, manifestDstPath)
121
122         common.execArgs([
123                         common.ANDROID_BIN,
124                         'update', 'project',
125                         '--name', 'dEQP',
126                         '--path', '.',
127                         '--target', javaApi,
128                 ])
129
130         # Build
131         common.execArgs([
132                         common.ANT_BIN,
133                         "release" if isRelease else "debug",
134                         "-Dsource.dir=" + os.path.join(common.ANDROID_DIR, "package", "src"),
135                         "-Dresource.absolute.dir=" + os.path.join(common.ANDROID_DIR, "package", "res")
136                 ])
137
138 def signApp (keystore, keyname, storepass, keypass):
139         os.chdir(os.path.join(common.ANDROID_DIR, "package"))
140         common.execArgs([
141                         common.JARSIGNER_BIN,
142                         '-keystore', keystore,
143                         '-storepass', storepass,
144                         '-keypass', keypass,
145                         '-sigfile', 'CERT',
146                         '-digestalg', 'SHA1',
147                         '-sigalg', 'MD5withRSA',
148                         '-signedjar', 'bin/dEQP-unaligned.apk',
149                         'bin/dEQP-release-unsigned.apk',
150                         keyname
151                 ])
152         common.execArgs([
153                         common.ZIPALIGN_BIN,
154                         '-f', '4',
155                         'bin/dEQP-unaligned.apk',
156                         'bin/dEQP-release.apk'
157                 ])
158
159 def build (buildRoot=common.ANDROID_DIR, isRelease=False, nativeBuildType="Release", javaApi=common.ANDROID_JAVA_API, doParallelBuild=False):
160         curDir = os.getcwd()
161
162         try:
163                 assetsSrcDir = getAssetsDir(buildRoot, common.NATIVE_LIBS[0], nativeBuildType)
164                 assetsDstDir = os.path.join(buildRoot, "package", "assets")
165
166                 # Remove assets from the first build dir where we copy assets from
167                 # to avoid collecting cruft there.
168                 if os.path.exists(assetsSrcDir):
169                         shutil.rmtree(assetsSrcDir)
170                 if os.path.exists(assetsDstDir):
171                         shutil.rmtree(assetsDstDir)
172
173                 # Remove old libs dir to avoid collecting out-of-date versions
174                 # of libs for ABIs not built this time.
175                 libTargetDir = os.path.join(buildRoot, "package", "libs")
176                 if os.path.exists(libTargetDir):
177                         shutil.rmtree(libTargetDir)
178
179                 # Build native code
180                 nativeBuildArgs = [(buildRoot, libTargetDir, nativeLib, nativeBuildType) for nativeLib in common.NATIVE_LIBS]
181                 if doParallelBuild:
182                         common.parallelApply(buildNative, nativeBuildArgs)
183                 else:
184                         common.serialApply(buildNative, nativeBuildArgs)
185
186                 # Copy assets
187                 if os.path.exists(assetsSrcDir):
188                         shutil.copytree(assetsSrcDir, assetsDstDir)
189
190                 # Build java code and .apk
191                 buildApp(buildRoot, isRelease, javaApi)
192
193         finally:
194                 # Restore working dir
195                 os.chdir(curDir)
196
197 def dumpConfig ():
198         print " "
199         for entry in common.CONFIG_STRINGS:
200                 print "%-30s : %s" % (entry[0], entry[1])
201         print " "
202
203 if __name__ == "__main__":
204         parser = argparse.ArgumentParser()
205         parser.add_argument('--is-release', dest='isRelease', type=bool, default=False, help="Build android project in release mode.")
206         parser.add_argument('--native-build-type', dest='nativeBuildType', default="Release", help="Build type passed cmake when building native code.")
207         parser.add_argument('--build-root', dest='buildRoot', default=common.ANDROID_DIR, help="Root directory for storing build results.")
208         parser.add_argument('--dump-config', dest='dumpConfig', action='store_true', help="Print out all configurations variables")
209         parser.add_argument('--java-api', dest='javaApi', default=common.ANDROID_JAVA_API, help="Set the API signature for the java build.")
210         parser.add_argument('-p', '--parallel-build', dest='parallelBuild', action="store_true", help="Build native libraries in parallel.")
211
212         args = parser.parse_args()
213
214         if args.dumpConfig:
215                 dumpConfig()
216
217         build(buildRoot=os.path.abspath(args.buildRoot), isRelease=args.isRelease, nativeBuildType=args.nativeBuildType, javaApi=args.javaApi, doParallelBuild=args.parallelBuild)