xref: /aosp_15_r20/external/angle/scripts/gen_vk_gl_cts_build.py (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1#!/usr/bin/python3
2#  Copyright 2019 The ANGLE Project Authors. All rights reserved.
3#  Use of this source code is governed by a BSD-style license that can be
4#  found in the LICENSE file.
5#
6#  Code generation for:
7#  - src/tests/deqp_support/BUILD.gn
8#  - src/tests/deqp_data.gni
9#  NOTE: don't run this script directly. Run scripts/run_code_generation.py.
10
11import errno
12import os
13import sys
14import shutil
15
16
17def initDataDirectories(dataDirectories):
18    dataDirectories.append(os.path.join("data", "gles2"))
19    dataDirectories.append(os.path.join("data", "gles3"))
20    dataDirectories.append(os.path.join("data", "gles31"))
21    dataDirectories.append(os.path.join("external", "graphicsfuzz", "data", "gles3"))
22    dataDirectories.append(
23        os.path.join("external", "openglcts", "data", "gl_cts", "data", "common"))
24    dataDirectories.append(
25        os.path.join("external", "openglcts", "data", "gl_cts", "data", "gles3"))
26    dataDirectories.append(
27        os.path.join("external", "openglcts", "data", "gl_cts", "data", "gles31"))
28    dataDirectories.append(
29        os.path.join("external", "openglcts", "data", "gl_cts", "data", "gles32"))
30
31
32def initPathReplacements(pathReplacements):
33    # The GraphicsFuzz data files need the 'external/graphicsfuzz/' prefix removed
34    pathToReplace = os.path.join("external", "graphicsfuzz", "")  # Include trailing slash
35    pathReplacements[pathToReplace] = ""
36    # The KHR dEQP tests expect a root prefix of "gl_cts" for some reason.
37    pathToReplace = os.path.join("external", "openglcts", "")  # Include trailing slash
38    pathReplacements[pathToReplace] = ""
39
40
41def createBuildGnFile(buildGnPath):
42    # Cleanup the old file
43    if os.path.exists(buildGnPath):
44        os.remove(buildGnPath)
45    # Make the new one
46    return open(buildGnPath, "w+")
47
48
49def createGniFile(gniFilename):
50    # Cleanup the old file
51    if os.path.exists(gniFilename):
52        os.remove(gniFilename)
53    # Make the new one
54    return open(gniFilename, "w+")
55
56
57def writeFileHeader(fileIn):
58    templateFileHeader = """# GENERATED FILE - DO NOT EDIT.
59# Generated by: {script_name}
60#
61# Copyright 2019 The ANGLE Project Authors. All rights reserved.
62# Use of this source code is governed by a BSD-style license that can be
63# found in the LICENSE file.
64
65"""
66
67    fileHeader = templateFileHeader.format(script_name=os.path.basename(__file__))
68    fileIn.write(fileHeader)
69
70
71def fixDestinationDirectory(pathReplacements, relativeDirectory):
72    for pathReplacement in pathReplacements:
73        if pathReplacement in relativeDirectory:
74            return relativeDirectory.replace(pathReplacement, pathReplacements[pathReplacement])
75    return relativeDirectory
76
77
78def convertPathToVarName(path):
79    return path.replace(os.sep, "_")
80
81
82def getCMakeLists(deqpSrcDir):
83    cmakeLists = []
84    for root, directories, filenames in os.walk(deqpSrcDir):
85        for filename in filenames:
86            relativeDirectory = os.path.relpath(root, deqpSrcDir)
87            if filename == "CMakeLists.txt":
88                cmakeLists.append(os.path.join(relativeDirectory, filename))
89    return cmakeLists
90
91
92def main():
93    # List of directories containing data files
94    dataDirectories = []
95    # List of directories to exclude from the copy
96    excludedDirectories = [
97        ".git",
98    ]
99    # List of files to exclude from the copy
100    excludedFilenames = [
101        "LICENSE",
102    ]
103    # Dictionary of parts of paths that need to be replaced
104    # Key: Part of path to be replaced
105    # Value: What to replace it with
106    pathReplacements = {}
107    # List of unique relative directories for the copy() command outputs
108    relativeDirectories = []
109    # VK-GL-CTS source directory
110    deqpSourceDirectory = os.path.join("..", "third_party", "VK-GL-CTS", "src")
111    # Tests Directory
112    testsDirectory = os.path.join("..", "src", "tests")
113    # dEQP Support Directory
114    deqpSupportDirectory = "deqp_support"
115    # BUILD.gn file to write to
116    buildGnFilename = "BUILD.gn"
117    # Path to BUILD.gn
118    buildGnPath = os.path.join(testsDirectory, deqpSupportDirectory, buildGnFilename)
119    # dEQP data GNI File to write to
120    dataGniFilename = os.path.join(testsDirectory, deqpSupportDirectory, "deqp_data_autogen.gni")
121
122    # run_code_generation.py parameters.
123    if len(sys.argv) > 1:
124        # All CMakeLists.txt in the dEQP source tree (at the time)
125        cmakeDirs = getCMakeLists(deqpSourceDirectory)
126        inputs = [os.path.join(deqpSourceDirectory, "%s" % dir) for dir in cmakeDirs]
127        outputs = [dataGniFilename, buildGnPath]
128
129        if sys.argv[1] == 'inputs':
130            print(','.join(inputs))
131        elif sys.argv[1] == 'outputs':
132            print(','.join(outputs))
133        else:
134            print('Invalid script parameters')
135            return 1
136        return 0
137
138    deqpSrcDir = os.path.abspath(os.path.join(sys.path[0], deqpSourceDirectory))
139
140    initDataDirectories(dataDirectories)
141    initPathReplacements(pathReplacements)
142
143    dataFiles = []
144    for dataDir in dataDirectories:
145        dataPath = os.path.join(deqpSrcDir, dataDir)
146        for root, directories, filenames in os.walk(dataPath):
147            for filename in filenames:
148                relativeDirectory = os.path.relpath(root, deqpSrcDir)
149                # Skip any excluded directories
150                if any(directory in relativeDirectory for directory in excludedDirectories):
151                    continue
152                # Skip any excluded files
153                if any(excludedFilename in filename for excludedFilename in excludedFilenames):
154                    continue
155                # Record the relative directories and full paths to each data file
156                if relativeDirectory not in relativeDirectories:
157                    relativeDirectories.append(relativeDirectory)
158                dataFiles.append(os.path.join(relativeDirectory, filename))
159
160    dataFiles.sort()
161    relativeDirectories.sort(key=convertPathToVarName)
162
163    #
164    # BUILD.gn
165    #
166    buildGnFile = createBuildGnFile(buildGnPath)
167    writeFileHeader(buildGnFile)
168    # Definitions
169    buildGnFile.write("deqp_path = \"../../../third_party/VK-GL-CTS/src\"\n")
170    # Create the copy() commands
171    templateFilesToCopy = """    "$deqp_path/{dataFile}",
172"""
173    templateCopyCommand = """
174copy("vk_gl_cts_data_{relDir}") {{
175  sources = [
176    {filesToCopy}
177  ]
178  outputs = [ "$root_gen_dir/vk_gl_cts_data/{destDir}/{{{{source_file_part}}}}" ]
179}}
180"""
181    for relativeDirectory in relativeDirectories:
182        filesToCopy = ""
183        for dataFile in dataFiles:
184            path, filename = os.path.split(dataFile)
185            if relativeDirectory == path:
186                filesToCopy += templateFilesToCopy.format(dataFile=dataFile.replace(os.sep, '/'))
187        copyCommand = ""
188        destDir = fixDestinationDirectory(pathReplacements, relativeDirectory)
189        copyCommand += templateCopyCommand.format(
190            relDir=convertPathToVarName(relativeDirectory),
191            filesToCopy=filesToCopy,
192            destDir=destDir.replace(os.sep, '/'))
193        buildGnFile.write(copyCommand)
194
195    #
196    # .gni
197    #
198    gniFile = createGniFile(dataGniFilename)
199    writeFileHeader(gniFile)
200    # Imports
201    templateImports = """import("deqp.gni")
202"""
203    gniFile.write(templateImports)
204    # Write the lists of data file dependencies
205    templateDataFiles = """  "$root_gen_dir/vk_gl_cts_data/{dataFile}",
206"""
207    templateDataFileDeps = """
208{dataDepName} = [
209{files}]
210"""
211    for dataDirectory in dataDirectories:
212        files = ""
213        for dataFile in dataFiles:
214            if dataDirectory + os.sep in dataFile:
215                files += templateDataFiles.format(
216                    dataFile=fixDestinationDirectory(pathReplacements, dataFile).replace(
217                        os.sep, '/'))
218        dataDepName = "angle_deqp_" + convertPathToVarName(dataDirectory)
219        fileDeps = templateDataFileDeps.format(dataDepName=dataDepName, files=files)
220        gniFile.write(fileDeps)
221
222    templateCopyTarget = """  "{deqpSupportDirectory}:vk_gl_cts_data_{relDir}",
223"""
224    templateCopyTargets = """
225angle_deqp_data_copy_targets = [
226{targets}]
227"""
228    targets = ""
229    for relativeDirectory in relativeDirectories:
230        targets += templateCopyTarget.format(
231            deqpSupportDirectory=deqpSupportDirectory,
232            relDir=convertPathToVarName(relativeDirectory))
233    gniFile.write(templateCopyTargets.format(targets=targets))
234
235
236if __name__ == '__main__':
237    sys.exit(main())
238