|
15 | 15 | #include <cassert> |
16 | 16 | #include <cstdio> |
17 | 17 | #include <cstring> |
| 18 | +#include <filesystem> |
18 | 19 | #include <iostream> |
19 | 20 | #include <vector> |
20 | 21 |
|
|
27 | 28 | void print_usage(char* argv0) { |
28 | 29 | std::string target_env_list = spvTargetEnvList(36, 105); |
29 | 30 | printf( |
30 | | - R"(%s - Validate a SPIR-V binary file. |
| 31 | + R"(%s - Validate a SPIR-V binary file(s). |
31 | 32 |
|
32 | | -USAGE: %s [options] [<filename>] |
| 33 | +USAGE: %s [options] [<path>] |
33 | 34 |
|
34 | | -The SPIR-V binary is read from <filename>. If no file is specified, |
35 | | -or if the filename is "-", then the binary is read from standard input. |
| 35 | +The SPIR-V binary is read from <path>. If no path is specified, |
| 36 | +or if the path is "-", then the binary is read from standard input. |
| 37 | +The <path> parameter may also specify a directory; in this case, |
| 38 | +the tool will recursively process all regular files with the .spv |
| 39 | +extension within that directory. |
36 | 40 |
|
37 | 41 | NOTE: The validator is a work in progress. |
38 | 42 |
|
@@ -79,6 +83,53 @@ NOTE: The validator is a work in progress. |
79 | 83 | argv0, argv0, target_env_list.c_str()); |
80 | 84 | } |
81 | 85 |
|
| 86 | +bool process_single_file(const char* filename, spv_target_env& target_env, |
| 87 | + spvtools::ValidatorOptions& options, |
| 88 | + bool use_default_msg_consumer) { |
| 89 | + std::vector<uint32_t> contents; |
| 90 | + if (!ReadBinaryFile(filename, &contents)) return false; |
| 91 | + |
| 92 | + spvtools::SpirvTools tools(target_env); |
| 93 | + |
| 94 | + // Use a lambda expression here so filename can be captured. Messages use a |
| 95 | + // fairly standard notation of `filename:line`. |
| 96 | + auto CLIMessageConsumerWithFilename = |
| 97 | + [filename](spv_message_level_t level, const char*, |
| 98 | + const spv_position_t& position, const char* message) { |
| 99 | + const char* pretty_filename = filename; |
| 100 | + if (!filename || 0 == strcmp(filename, "-")) { |
| 101 | + pretty_filename = "stdin"; |
| 102 | + } |
| 103 | + |
| 104 | + switch (level) { |
| 105 | + case SPV_MSG_FATAL: |
| 106 | + case SPV_MSG_INTERNAL_ERROR: |
| 107 | + case SPV_MSG_ERROR: |
| 108 | + std::cerr << "error: " << pretty_filename << ":" << position.index |
| 109 | + << ": " << message << std::endl; |
| 110 | + break; |
| 111 | + case SPV_MSG_WARNING: |
| 112 | + std::cout << "warning: " << pretty_filename << ":" << position.index |
| 113 | + << ": " << message << std::endl; |
| 114 | + break; |
| 115 | + case SPV_MSG_INFO: |
| 116 | + std::cout << "info: " << pretty_filename << ":" << position.index |
| 117 | + << ": " << message << std::endl; |
| 118 | + break; |
| 119 | + default: |
| 120 | + break; |
| 121 | + } |
| 122 | + }; |
| 123 | + |
| 124 | + if (use_default_msg_consumer) { |
| 125 | + tools.SetMessageConsumer(spvtools::utils::CLIMessageConsumer); |
| 126 | + } else { |
| 127 | + tools.SetMessageConsumer(CLIMessageConsumerWithFilename); |
| 128 | + } |
| 129 | + |
| 130 | + return tools.Validate(contents.data(), contents.size(), options); |
| 131 | +} |
| 132 | + |
82 | 133 | int main(int argc, char** argv) { |
83 | 134 | const char* inFile = nullptr; |
84 | 135 | spv_target_env target_env = SPV_ENV_UNIVERSAL_1_6; |
@@ -201,13 +252,28 @@ int main(int argc, char** argv) { |
201 | 252 | return return_code; |
202 | 253 | } |
203 | 254 |
|
204 | | - std::vector<uint32_t> contents; |
205 | | - if (!ReadBinaryFile(inFile, &contents)) return 1; |
| 255 | + if (inFile && |
| 256 | + std::filesystem::is_directory(std::filesystem::status(inFile))) { |
| 257 | + const std::filesystem::path dir(inFile); |
| 258 | + bool succeed = true; |
| 259 | + for (auto const& entry : |
| 260 | + std::filesystem::recursive_directory_iterator(dir)) { |
| 261 | + if (!entry.is_regular_file()) { |
| 262 | + continue; |
| 263 | + } |
206 | 264 |
|
207 | | - spvtools::SpirvTools tools(target_env); |
208 | | - tools.SetMessageConsumer(spvtools::utils::CLIMessageConsumer); |
| 265 | + std::filesystem::path filepath = entry.path(); |
209 | 266 |
|
210 | | - bool succeed = tools.Validate(contents.data(), contents.size(), options); |
| 267 | + if (filepath.extension() != ".spv") continue; |
| 268 | + |
| 269 | + if (!process_single_file(filepath.u8string().c_str(), target_env, options, |
| 270 | + false)) { |
| 271 | + succeed = false; |
| 272 | + } |
| 273 | + } |
| 274 | + |
| 275 | + return !succeed; |
| 276 | + } |
211 | 277 |
|
212 | | - return !succeed; |
| 278 | + return !process_single_file(inFile, target_env, options, true); |
213 | 279 | } |
0 commit comments