John Stiles | d836f84 | 2020-09-14 10:21:44 -0400 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | # |
| 3 | # Copyright 2020 Google LLC |
| 4 | # |
| 5 | # Use of this source code is governed by a BSD-style license that can be |
| 6 | # found in the LICENSE file. |
| 7 | |
| 8 | import os |
John Stiles | b7f5e1b | 2021-01-27 14:05:15 -0500 | [diff] [blame] | 9 | import shlex |
John Stiles | d836f84 | 2020-09-14 10:21:44 -0400 | [diff] [blame] | 10 | import subprocess |
| 11 | import sys |
Brian Osman | 7b23905 | 2020-11-18 17:04:33 +0000 | [diff] [blame] | 12 | import tempfile |
John Stiles | d836f84 | 2020-09-14 10:21:44 -0400 | [diff] [blame] | 13 | |
John Stiles | b7f5e1b | 2021-01-27 14:05:15 -0500 | [diff] [blame] | 14 | batchCompile = True |
| 15 | |
John Stiles | 0ed9f31 | 2020-09-16 17:46:37 -0400 | [diff] [blame] | 16 | skslc = sys.argv[1] |
John Stiles | 7e24871 | 2020-09-24 16:42:09 -0400 | [diff] [blame] | 17 | lang = sys.argv[2] |
| 18 | settings = sys.argv[3] |
John Stiles | b7f5e1b | 2021-01-27 14:05:15 -0500 | [diff] [blame] | 19 | with open(sys.argv[4], 'r') as reader: |
| 20 | inputs = shlex.split(reader.read()) |
John Stiles | f92f89b | 2021-01-12 14:05:05 -0500 | [diff] [blame] | 21 | |
John Stiles | da57fc0 | 2021-01-22 11:54:30 -0500 | [diff] [blame] | 22 | def pairwise(iterable): |
| 23 | # Iterate over an array pairwise (two elements at a time). |
| 24 | a = iter(iterable) |
| 25 | return zip(a, a) |
| 26 | |
John Stiles | f92f89b | 2021-01-12 14:05:05 -0500 | [diff] [blame] | 27 | def executeWorklist(input, worklist): |
| 28 | # Invoke skslc, passing in the worklist. |
| 29 | worklist.close() |
| 30 | try: |
| 31 | output = subprocess.check_output([skslc, worklist.name], stderr=subprocess.STDOUT) |
| 32 | except subprocess.CalledProcessError as err: |
| 33 | if err.returncode != 1: |
| 34 | print("### " + input + " skslc error:\n") |
| 35 | print("\n".join(err.output.splitlines())) |
| 36 | sys.exit(err.returncode) |
| 37 | pass # Compile errors (exit code 1) are expected and normal in test code |
| 38 | |
| 39 | # Delete the worklist file now that execution is complete. |
| 40 | os.remove(worklist.name) |
John Stiles | 0ed9f31 | 2020-09-16 17:46:37 -0400 | [diff] [blame] | 41 | |
John Stiles | 886b9d4 | 2020-09-15 11:16:10 -0400 | [diff] [blame] | 42 | def makeEmptyFile(path): |
John Stiles | ea9e7ca | 2020-09-14 16:46:40 -0400 | [diff] [blame] | 43 | try: |
John Stiles | 886b9d4 | 2020-09-15 11:16:10 -0400 | [diff] [blame] | 44 | open(path, 'wb').close() |
John Stiles | ea9e7ca | 2020-09-14 16:46:40 -0400 | [diff] [blame] | 45 | except OSError: |
| 46 | pass |
| 47 | |
John Stiles | dda1d31 | 2020-11-20 16:28:50 -0500 | [diff] [blame] | 48 | def extensionForSpirvAsm(ext): |
John Stiles | 92072a3 | 2020-11-23 15:14:35 -0500 | [diff] [blame] | 49 | return ext if (ext == '.frag' or ext == '.vert' or ext == '.geom') else '.frag' |
John Stiles | dda1d31 | 2020-11-20 16:28:50 -0500 | [diff] [blame] | 50 | |
John Stiles | 0ed9f31 | 2020-09-16 17:46:37 -0400 | [diff] [blame] | 51 | if settings != "--settings" and settings != "--nosettings": |
John Stiles | 7e24871 | 2020-09-24 16:42:09 -0400 | [diff] [blame] | 52 | sys.exit("### Expected --settings or --nosettings, got " + settings) |
John Stiles | d836f84 | 2020-09-14 10:21:44 -0400 | [diff] [blame] | 53 | |
John Stiles | a1e8fe3 | 2020-11-11 17:29:28 -0500 | [diff] [blame] | 54 | targets = [] |
John Stiles | 57adba0 | 2020-11-18 13:58:19 -0500 | [diff] [blame] | 55 | worklist = tempfile.NamedTemporaryFile(suffix='.worklist', delete=False) |
John Stiles | a1e8fe3 | 2020-11-11 17:29:28 -0500 | [diff] [blame] | 56 | |
John Stiles | da57fc0 | 2021-01-22 11:54:30 -0500 | [diff] [blame] | 57 | # The `inputs` array pairs off input files with their matching output directory, e.g.: |
| 58 | # //skia/tests/sksl/shared/test.sksl |
| 59 | # //skia/tests/sksl/shared/golden/ |
| 60 | # //skia/tests/sksl/intrinsics/abs.sksl |
| 61 | # //skia/tests/sksl/intrinsics/golden/ |
| 62 | # ... (etc) ... |
| 63 | # Here we loop over these inputs and convert them into a worklist file for skslc. |
| 64 | for input, targetDir in pairwise(inputs): |
John Stiles | dda1d31 | 2020-11-20 16:28:50 -0500 | [diff] [blame] | 65 | noExt, ext = os.path.splitext(input) |
John Stiles | ea9e7ca | 2020-09-14 16:46:40 -0400 | [diff] [blame] | 66 | head, tail = os.path.split(noExt) |
John Stiles | ea9e7ca | 2020-09-14 16:46:40 -0400 | [diff] [blame] | 67 | if not os.path.isdir(targetDir): |
| 68 | os.mkdir(targetDir) |
John Stiles | 0ed9f31 | 2020-09-16 17:46:37 -0400 | [diff] [blame] | 69 | |
John Stiles | ea9e7ca | 2020-09-14 16:46:40 -0400 | [diff] [blame] | 70 | target = os.path.join(targetDir, tail) |
John Stiles | 0ed9f31 | 2020-09-16 17:46:37 -0400 | [diff] [blame] | 71 | if settings == "--nosettings": |
John Stiles | 371fde5 | 2020-09-21 17:09:52 -0400 | [diff] [blame] | 72 | target += "StandaloneSettings" |
John Stiles | 0ed9f31 | 2020-09-16 17:46:37 -0400 | [diff] [blame] | 73 | |
John Stiles | a1e8fe3 | 2020-11-11 17:29:28 -0500 | [diff] [blame] | 74 | targets.append(target) |
| 75 | |
John Stiles | 7e24871 | 2020-09-24 16:42:09 -0400 | [diff] [blame] | 76 | if lang == "--fp": |
Brian Osman | 7b23905 | 2020-11-18 17:04:33 +0000 | [diff] [blame] | 77 | worklist.write(input + "\n") |
| 78 | worklist.write(target + ".cpp\n") |
| 79 | worklist.write(settings + "\n\n") |
| 80 | worklist.write(input + "\n") |
| 81 | worklist.write(target + ".h\n") |
| 82 | worklist.write(settings + "\n\n") |
John Stiles | 82ab340 | 2021-04-13 17:13:03 -0400 | [diff] [blame] | 83 | elif lang == "--dslfp": |
| 84 | worklist.write(input + "\n") |
John Stiles | 0a0a50a | 2021-04-14 09:35:24 -0400 | [diff] [blame] | 85 | worklist.write(target + ".dsl.cpp\n") |
John Stiles | 82ab340 | 2021-04-13 17:13:03 -0400 | [diff] [blame] | 86 | worklist.write(settings + "\n\n") |
| 87 | worklist.write(input + "\n") |
| 88 | worklist.write(target + ".h\n") |
| 89 | worklist.write(settings + "\n\n") |
John Stiles | 7e24871 | 2020-09-24 16:42:09 -0400 | [diff] [blame] | 90 | elif lang == "--glsl": |
Brian Osman | 7b23905 | 2020-11-18 17:04:33 +0000 | [diff] [blame] | 91 | worklist.write(input + "\n") |
| 92 | worklist.write(target + ".glsl\n") |
| 93 | worklist.write(settings + "\n\n") |
John Stiles | aeae3a5 | 2020-09-25 13:35:58 -0400 | [diff] [blame] | 94 | elif lang == "--metal": |
Brian Osman | 7b23905 | 2020-11-18 17:04:33 +0000 | [diff] [blame] | 95 | worklist.write(input + "\n") |
| 96 | worklist.write(target + ".metal\n") |
| 97 | worklist.write(settings + "\n\n") |
John Stiles | dda1d31 | 2020-11-20 16:28:50 -0500 | [diff] [blame] | 98 | elif lang == "--spirv": |
| 99 | worklist.write(input + "\n") |
John Stiles | 92072a3 | 2020-11-23 15:14:35 -0500 | [diff] [blame] | 100 | worklist.write(target + ".asm" + extensionForSpirvAsm(ext) + "\n") |
John Stiles | dda1d31 | 2020-11-20 16:28:50 -0500 | [diff] [blame] | 101 | worklist.write(settings + "\n\n") |
Brian Osman | 977feec | 2020-12-22 11:28:59 -0500 | [diff] [blame] | 102 | elif lang == "--skvm": |
| 103 | worklist.write(input + "\n") |
| 104 | worklist.write(target + ".skvm\n") |
| 105 | worklist.write(settings + "\n\n") |
Brian Osman | 62b039b | 2021-02-08 13:49:53 -0500 | [diff] [blame] | 106 | elif lang == "--stage": |
| 107 | worklist.write(input + "\n") |
| 108 | worklist.write(target + ".stage\n") |
| 109 | worklist.write(settings + "\n\n") |
John Stiles | ea9e7ca | 2020-09-14 16:46:40 -0400 | [diff] [blame] | 110 | else: |
John Stiles | 82ab340 | 2021-04-13 17:13:03 -0400 | [diff] [blame] | 111 | sys.exit("### Expected one of: --fp --dslfp --glsl --metal --spirv --skvm --stage, got " + |
| 112 | lang) |
John Stiles | a1e8fe3 | 2020-11-11 17:29:28 -0500 | [diff] [blame] | 113 | |
John Stiles | f92f89b | 2021-01-12 14:05:05 -0500 | [diff] [blame] | 114 | # Compile items one at a time. |
| 115 | if not batchCompile: |
| 116 | executeWorklist(input, worklist) |
| 117 | worklist = tempfile.NamedTemporaryFile(suffix='.worklist', delete=False) |
John Stiles | a1e8fe3 | 2020-11-11 17:29:28 -0500 | [diff] [blame] | 118 | |
John Stiles | f92f89b | 2021-01-12 14:05:05 -0500 | [diff] [blame] | 119 | # Compile everything all in one go. |
| 120 | if batchCompile: |
| 121 | executeWorklist("", worklist) |
| 122 | else: |
| 123 | worklist.close() |
| 124 | os.remove(worklist.name) |
John Stiles | 57adba0 | 2020-11-18 13:58:19 -0500 | [diff] [blame] | 125 | |
John Stiles | a1e8fe3 | 2020-11-11 17:29:28 -0500 | [diff] [blame] | 126 | # A special case cleanup pass, just for CPP and H files: if either one of these files starts with |
| 127 | # `### Compilation failed`, its sibling should be replaced by an empty file. This improves clarity |
| 128 | # during code review; a failure on either file means that success on the sibling is irrelevant. |
John Stiles | 82ab340 | 2021-04-13 17:13:03 -0400 | [diff] [blame] | 129 | if lang == "--fp" or lang == "--dslfp": |
John Stiles | 0a0a50a | 2021-04-14 09:35:24 -0400 | [diff] [blame] | 130 | cppExtension = (".dsl.cpp" if lang == "--dslfp" else ".cpp") |
John Stiles | 82ab340 | 2021-04-13 17:13:03 -0400 | [diff] [blame] | 131 | hExtension = ".h" |
| 132 | |
John Stiles | a1e8fe3 | 2020-11-11 17:29:28 -0500 | [diff] [blame] | 133 | for target in targets: |
John Stiles | 82ab340 | 2021-04-13 17:13:03 -0400 | [diff] [blame] | 134 | cppFile = open(target + cppExtension, 'r') |
| 135 | hFile = open(target + hExtension, 'r') |
John Stiles | a1e8fe3 | 2020-11-11 17:29:28 -0500 | [diff] [blame] | 136 | if cppFile.readline().startswith("### Compilation failed"): |
| 137 | # The CPP had a compilation failure. Clear the header file. |
| 138 | hFile.close() |
John Stiles | 82ab340 | 2021-04-13 17:13:03 -0400 | [diff] [blame] | 139 | makeEmptyFile(target + hExtension) |
John Stiles | a1e8fe3 | 2020-11-11 17:29:28 -0500 | [diff] [blame] | 140 | elif hFile.readline().startswith("### Compilation failed"): |
| 141 | # The header had a compilation failure. Clear the CPP file. |
| 142 | cppFile.close() |
John Stiles | 82ab340 | 2021-04-13 17:13:03 -0400 | [diff] [blame] | 143 | makeEmptyFile(target + cppExtension) |