6 #include <system_error>
8 #include "flutter/fml/backtrace.h"
9 #include "flutter/fml/command_line.h"
10 #include "flutter/fml/file.h"
11 #include "flutter/fml/mapping.h"
25 Reflector::Options CreateReflectorOptions(
const SourceOptions& options,
26 const Switches& switches) {
27 Reflector::Options reflector_options;
28 reflector_options.target_platform = options.target_platform;
29 reflector_options.entry_point_name = options.entry_point_name;
30 reflector_options.shader_name =
32 reflector_options.header_file_name =
33 Utf8FromPath(switches.reflection_header_name.filename());
34 return reflector_options;
39 const std::shared_ptr<const fml::Mapping>& source_file_mapping,
40 const Switches& switches) {
41 SourceOptions options = switches.CreateSourceOptions();
42 options.target_platform = platform;
43 Reflector::Options reflector_options =
44 CreateReflectorOptions(options, switches);
45 return std::make_shared<Compiler>(source_file_mapping, options,
49 void OutputVerboseErrorFile(
const std::string& verbose_error_messages,
50 const Switches& switches) {
51 auto error_mapping = std::make_shared<fml::NonOwnedMapping>(
52 reinterpret_cast<const uint8_t*
>(verbose_error_messages.data()),
53 verbose_error_messages.size(), [](
auto,
auto) {});
54 std::filesystem::path output_path =
55 std::filesystem::path(fml::CreateTemporaryDirectory()) /
56 "impellerc_verbose_error.txt";
58 if (fml::WriteAtomically(*switches.working_directory,
61 <<
"\" error output written to " << output_path << std::endl;
63 std::cerr <<
"Failed to write full \""
65 <<
"\" error output to " << output_path << std::endl;
69 bool OutputIPLR(
const std::vector<std::shared_ptr<Compiler>>& compilers,
70 const Switches& switches) {
71 FML_DCHECK(switches.iplr);
73 RuntimeStageData stages;
74 for (
const auto& compiler : compilers) {
75 std::shared_ptr<RuntimeStageData::Shader> stage_data =
76 compiler->GetReflector()->GetRuntimeStageShaderData();
78 std::cerr <<
"Runtime stage information was nil." << std::endl;
81 stages.AddShader(stage_data);
84 auto stage_data_mapping = switches.json_format ? stages.CreateJsonMapping()
85 : stages.CreateMapping();
86 if (!stage_data_mapping) {
87 std::cerr <<
"Runtime stage data could not be created." << std::endl;
90 if (!fml::WriteAtomically(*switches.working_directory,
94 std::cerr <<
"Could not write file to " << switches.sl_file_name
106 bool OutputSLFile(
const Compiler& compiler,
const Switches& switches) {
107 auto sl_file_name = std::filesystem::absolute(
108 std::filesystem::current_path() / switches.sl_file_name);
109 if (!fml::WriteAtomically(*switches.working_directory,
111 *compiler.GetSLShaderSource())) {
112 std::cerr <<
"Could not write file to " << switches.sl_file_name
119 bool OutputSPIRV(
const Compiler& compiler,
const Switches& switches) {
120 auto spriv_file_name = std::filesystem::absolute(
121 std::filesystem::current_path() / switches.spirv_file_name);
122 if (!fml::WriteAtomically(*switches.working_directory,
124 *compiler.GetSPIRVAssembly())) {
125 std::cerr <<
"Could not write file to " << switches.spirv_file_name
132 bool ShouldOutputReflectionData(
const Switches& switches) {
133 return !switches.reflection_json_name.empty() ||
134 !switches.reflection_header_name.empty() ||
135 !switches.reflection_cc_name.empty();
138 bool OutputReflectionData(
const Compiler& compiler,
const Switches& switches) {
139 if (!switches.reflection_json_name.empty()) {
140 auto reflection_json_name = std::filesystem::absolute(
141 std::filesystem::current_path() / switches.reflection_json_name);
142 if (!fml::WriteAtomically(*switches.working_directory,
144 *compiler.GetReflector()->GetReflectionJSON())) {
145 std::cerr <<
"Could not write reflection json to "
146 << switches.reflection_json_name << std::endl;
151 if (!switches.reflection_header_name.empty()) {
152 auto reflection_header_name = std::filesystem::absolute(
153 std::filesystem::current_path() / switches.reflection_header_name);
154 if (!fml::WriteAtomically(
155 *switches.working_directory,
157 *compiler.GetReflector()->GetReflectionHeader())) {
158 std::cerr <<
"Could not write reflection header to "
159 << switches.reflection_header_name << std::endl;
164 if (!switches.reflection_cc_name.empty()) {
165 auto reflection_cc_name = std::filesystem::absolute(
166 std::filesystem::current_path() / switches.reflection_cc_name);
167 if (!fml::WriteAtomically(*switches.working_directory,
169 *compiler.GetReflector()->GetReflectionCC())) {
170 std::cerr <<
"Could not write reflection CC to "
171 << switches.reflection_cc_name << std::endl;
178 bool OutputDepfile(
const Compiler& compiler,
const Switches& switches) {
179 if (!switches.depfile_path.empty()) {
180 std::string result_file =
Utf8FromPath(switches.sl_file_name);
181 auto depfile_path = std::filesystem::absolute(
182 std::filesystem::current_path() / switches.depfile_path);
183 if (!fml::WriteAtomically(*switches.working_directory,
185 *compiler.CreateDepfileContents({result_file}))) {
186 std::cerr <<
"Could not write depfile to " << switches.depfile_path
197 bool Main(
const fml::CommandLine& command_line) {
198 fml::InstallCrashHandler();
199 if (command_line.HasOption(
"help")) {
205 if (!switches.
AreValid(std::cerr)) {
206 std::cerr <<
"Invalid flags specified." << std::endl;
217 std::shared_ptr<fml::FileMapping> source_file_mapping =
219 if (!source_file_mapping) {
220 std::cerr <<
"Could not open input file." << std::endl;
224 std::vector<std::shared_ptr<Compiler>> compilers;
227 std::shared_ptr<Compiler> compiler =
229 if (compiler->IsValid()) {
230 compilers.push_back(compiler);
232 std::cerr <<
"Compilation failed for target: "
235 std::string verbose_error_messages = compiler->GetVerboseErrorMessages();
236 if (verbose_error_messages.empty()) {
238 std::cerr << compiler->GetErrorMessages();
243 std::cerr << verbose_error_messages;
248 std::cerr << compiler->GetErrorMessages();
249 OutputVerboseErrorFile(verbose_error_messages, switches);
264 if (!OutputIPLR(compilers, switches)) {
270 FML_DCHECK(compilers.size() == 1);
271 if (!OutputSLFile(*compilers.front(), switches)) {
281 auto first_valid_compiler = compilers.front();
287 if (!OutputSPIRV(*first_valid_compiler, switches)) {
296 if (ShouldOutputReflectionData(switches)) {
298 FML_DCHECK(compilers.size() == 1);
299 if (!OutputReflectionData(*first_valid_compiler, switches)) {
310 if (!OutputDepfile(*first_valid_compiler, switches)) {
320 int main(
int argc,
char const* argv[]) {
322 fml::CommandLineFromPlatformOrArgcArgv(argc, argv))
std::vector< TargetPlatform > PlatformsToCompile() const
A vector containing at least one valid platform.
std::string shader_bundle
bool AreValid(std::ostream &explain) const
static void PrintHelp(std::ostream &stream)
std::filesystem::path source_file_name
int main(int argc, char const *argv[])
bool Main(const fml::CommandLine &command_line)
std::string TargetPlatformToString(TargetPlatform platform)
bool SetPermissiveAccess(const std::filesystem::path &p)
Sets the file access mode of the file at path 'p' to 0644.
std::string InferShaderNameFromPath(const std::filesystem::path &path)
bool GenerateShaderBundle(Switches &switches)
Parses the JSON shader bundle configuration and invokes the compiler multiple times to produce a shad...
static CompilerBackend CreateCompiler(const spirv_cross::ParsedIR &ir, const SourceOptions &source_options)
std::string Utf8FromPath(const std::filesystem::path &path)
Converts a native format path to a utf8 string.