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