| Flutter Impeller |

impellerc_main.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <filesystem>
6 #include <system_error>
7
8 #include "flutter/fml/backtrace.h"
9 #include "flutter/fml/command_line.h"
10 #include "flutter/fml/file.h"
11 #include "flutter/fml/macros.h"
12 #include "flutter/fml/mapping.h"
13 #include "impeller/base/strings.h"
14 #include "impeller/compiler/compiler.h"
15 #include "impeller/compiler/source_options.h"
16 #include "impeller/compiler/switches.h"
17 #include "impeller/compiler/types.h"
18 #include "impeller/compiler/utilities.h"
19 #include "third_party/shaderc/libshaderc/include/shaderc/shaderc.hpp"
20
21 namespace impeller {
22 namespace compiler {
23
24 // Sets the file access mode of the file at path 'p' to 0644.
25 static bool SetPermissiveAccess(const std::filesystem::path& p) {
26 auto permissions =
27 std::filesystem::perms::owner_read | std::filesystem::perms::owner_write |
28 std::filesystem::perms::group_read | std::filesystem::perms::others_read;
29 std::error_code error;
30 std::filesystem::permissions(p, permissions, error);
31 if (error) {
32 std::cerr << "Failed to set access on file '" << p
33 << "': " << error.message() << std::endl;
34 return false;
35 }
36 return true;
37 }
38
39 bool Main(const fml::CommandLine& command_line) {
40 fml::InstallCrashHandler();
41 if (command_line.HasOption("help")) {
42 Switches::PrintHelp(std::cout);
43 return true;
44 }
45
46 Switches switches(command_line);
47 if (!switches.AreValid(std::cerr)) {
48 std::cerr << "Invalid flags specified." << std::endl;
49 Switches::PrintHelp(std::cerr);
50 return false;
51 }
52
53 std::shared_ptr<fml::FileMapping> source_file_mapping =
54 fml::FileMapping::CreateReadOnly(switches.source_file_name);
55 if (!source_file_mapping) {
56 std::cerr << "Could not open input file." << std::endl;
57 return false;
58 }
59
60 SourceOptions options;
61 options.target_platform = switches.target_platform;
62 options.source_language = switches.source_language;
63 if (switches.input_type == SourceType::kUnknown) {
64 options.type = SourceTypeFromFileName(switches.source_file_name);
65 } else {
66 options.type = switches.input_type;
67 }
68 options.working_directory = switches.working_directory;
69 options.file_name = switches.source_file_name;
70 options.include_dirs = switches.include_directories;
71 options.defines = switches.defines;
72 options.entry_point_name = EntryPointFunctionNameFromSourceName(
73 switches.source_file_name, options.type, options.source_language,
74 switches.entry_point);
75 options.json_format = switches.json_format;
76 options.gles_language_version = switches.gles_language_version;
77 options.metal_version = switches.metal_version;
78 options.use_half_textures = switches.use_half_textures;
79
80 Reflector::Options reflector_options;
81 reflector_options.target_platform = switches.target_platform;
82 reflector_options.entry_point_name = options.entry_point_name;
83 reflector_options.shader_name =
84 InferShaderNameFromPath(switches.source_file_name);
85 reflector_options.header_file_name = Utf8FromPath(
86 std::filesystem::path{switches.reflection_header_name}.filename());
87
88 // Generate SkSL if needed.
89 std::shared_ptr<fml::Mapping> sksl_mapping;
90 if (switches.iplr && TargetPlatformBundlesSkSL(switches.target_platform)) {
91 SourceOptions sksl_options = options;
92 sksl_options.target_platform = TargetPlatform::kSkSL;
93
94 Reflector::Options sksl_reflector_options = reflector_options;
95 sksl_reflector_options.target_platform = TargetPlatform::kSkSL;
96
97 Compiler sksl_compiler =
98 Compiler(source_file_mapping, sksl_options, sksl_reflector_options);
99 if (!sksl_compiler.IsValid()) {
100 std::cerr << "Compilation to SkSL failed." << std::endl;
101 std::cerr << sksl_compiler.GetErrorMessages() << std::endl;
102 return false;
103 }
104 sksl_mapping = sksl_compiler.GetSLShaderSource();
105 }
106
107 Compiler compiler(source_file_mapping, options, reflector_options);
108 if (!compiler.IsValid()) {
109 std::cerr << "Compilation failed." << std::endl;
110 std::cerr << compiler.GetErrorMessages() << std::endl;
111 return false;
112 }
113
114 auto spriv_file_name = std::filesystem::absolute(
115 std::filesystem::current_path() / switches.spirv_file_name);
116 if (!fml::WriteAtomically(*switches.working_directory,
117 Utf8FromPath(spriv_file_name).c_str(),
118 *compiler.GetSPIRVAssembly())) {
119 std::cerr << "Could not write file to " << switches.spirv_file_name
120 << std::endl;
121 return false;
122 }
123
124 auto sl_file_name = std::filesystem::absolute(
125 std::filesystem::current_path() / switches.sl_file_name);
126 if (switches.iplr) {
127 auto reflector = compiler.GetReflector();
128 if (reflector == nullptr) {
129 std::cerr << "Could not create reflector." << std::endl;
130 return false;
131 }
132 auto stage_data = reflector->GetRuntimeStageData();
133 if (!stage_data) {
134 std::cerr << "Runtime stage information was nil." << std::endl;
135 return false;
136 }
137 if (sksl_mapping) {
138 stage_data->SetSkSLData(sksl_mapping);
139 }
140 auto stage_data_mapping = options.json_format
141 ? stage_data->CreateJsonMapping()
142 : stage_data->CreateMapping();
143 if (!stage_data_mapping) {
144 std::cerr << "Runtime stage data could not be created." << std::endl;
145 return false;
146 }
147 if (!fml::WriteAtomically(*switches.working_directory, //
148 Utf8FromPath(sl_file_name).c_str(), //
149 *stage_data_mapping //
150 )) {
151 std::cerr << "Could not write file to " << switches.sl_file_name
152 << std::endl;
153 return false;
154 }
155 // Tools that consume the runtime stage data expect the access mode to
156 // be 0644.
157 if (!SetPermissiveAccess(sl_file_name)) {
158 return false;
159 }
160 } else {
161 if (!fml::WriteAtomically(*switches.working_directory,
162 Utf8FromPath(sl_file_name).c_str(),
163 *compiler.GetSLShaderSource())) {
164 std::cerr << "Could not write file to " << switches.sl_file_name
165 << std::endl;
166 return false;
167 }
168 }
169
170 if (TargetPlatformNeedsReflection(options.target_platform)) {
171 if (!switches.reflection_json_name.empty()) {
172 auto reflection_json_name = std::filesystem::absolute(
173 std::filesystem::current_path() / switches.reflection_json_name);
174 if (!fml::WriteAtomically(
175 *switches.working_directory,
176 Utf8FromPath(reflection_json_name).c_str(),
177 *compiler.GetReflector()->GetReflectionJSON())) {
178 std::cerr << "Could not write reflection json to "
179 << switches.reflection_json_name << std::endl;
180 return false;
181 }
182 }
183
184 if (!switches.reflection_header_name.empty()) {
185 auto reflection_header_name =
186 std::filesystem::absolute(std::filesystem::current_path() /
187 switches.reflection_header_name.c_str());
188 if (!fml::WriteAtomically(
189 *switches.working_directory,
190 Utf8FromPath(reflection_header_name).c_str(),
191 *compiler.GetReflector()->GetReflectionHeader())) {
192 std::cerr << "Could not write reflection header to "
193 << switches.reflection_header_name << std::endl;
194 return false;
195 }
196 }
197
198 if (!switches.reflection_cc_name.empty()) {
199 auto reflection_cc_name =
200 std::filesystem::absolute(std::filesystem::current_path() /
201 switches.reflection_cc_name.c_str());
202 if (!fml::WriteAtomically(*switches.working_directory,
203 Utf8FromPath(reflection_cc_name).c_str(),
204 *compiler.GetReflector()->GetReflectionCC())) {
205 std::cerr << "Could not write reflection CC to "
206 << switches.reflection_cc_name << std::endl;
207 return false;
208 }
209 }
210 }
211
212 if (!switches.depfile_path.empty()) {
213 std::string result_file;
214 switch (switches.target_platform) {
215 case TargetPlatform::kMetalDesktop:
216 case TargetPlatform::kMetalIOS:
217 case TargetPlatform::kOpenGLES:
218 case TargetPlatform::kOpenGLDesktop:
219 case TargetPlatform::kRuntimeStageMetal:
220 case TargetPlatform::kRuntimeStageGLES:
221 case TargetPlatform::kRuntimeStageVulkan:
222 case TargetPlatform::kSkSL:
223 case TargetPlatform::kVulkan:
224 result_file = switches.sl_file_name;
225 break;
226 case TargetPlatform::kUnknown:
227 result_file = switches.spirv_file_name;
228 break;
229 }
230 auto depfile_path = std::filesystem::absolute(
231 std::filesystem::current_path() / switches.depfile_path.c_str());
232 if (!fml::WriteAtomically(*switches.working_directory,
233 Utf8FromPath(depfile_path).c_str(),
234 *compiler.CreateDepfileContents({result_file}))) {
235 std::cerr << "Could not write depfile to " << switches.depfile_path
236 << std::endl;
237 return false;
238 }
239 }
240
241 return true;
242 }
243
244 } // namespace compiler
245 } // namespace impeller
246
247 int main(int argc, char const* argv[]) {
248 return impeller::compiler::Main(
249 fml::CommandLineFromPlatformOrArgcArgv(argc, argv))
250 ? EXIT_SUCCESS
251 : EXIT_FAILURE;
252 }
impeller::compiler::Switches::gles_language_version
uint32_t gles_language_version
Definition: switches.h:36
impeller::compiler::Compiler
Definition: compiler.h:24
impeller::compiler::Switches::defines
std::vector< std::string > defines
Definition: switches.h:33
impeller::compiler::Switches::entry_point
std::string entry_point
Definition: switches.h:38
impeller::compiler::SourceOptions::type
SourceType type
Definition: source_options.h:20
impeller::compiler::Compiler::CreateDepfileContents
std::unique_ptr< fml::Mapping > CreateDepfileContents(std::initializer_list< std::string > targets) const
Definition: compiler.cc:467
impeller::compiler::Switches
Definition: switches.h:20
impeller::compiler::Switches::target_platform
TargetPlatform target_platform
Definition: switches.h:21
impeller::compiler::SourceOptions::include_dirs
std::vector< IncludeDir > include_dirs
Definition: source_options.h:24
impeller::compiler::SourceType::kUnknown
@ kUnknown
impeller::compiler::Switches::metal_version
std::string metal_version
Definition: switches.h:37
impeller::compiler::TargetPlatform::kMetalDesktop
@ kMetalDesktop
impeller::compiler::Switches::working_directory
std::shared_ptr< fml::UniqueFD > working_directory
Definition: switches.h:22
impeller::compiler::SourceOptions::metal_version
std::string metal_version
Definition: source_options.h:30
impeller::compiler::SourceOptions
Definition: source_options.h:19
impeller::compiler::Switches::include_directories
std::vector< IncludeDir > include_directories
Definition: switches.h:23
impeller::compiler::SourceOptions::use_half_textures
bool use_half_textures
Whether half-precision textures should be supported, requiring opengl semantics. Only used on metal t...
Definition: source_options.h:34
impeller::compiler::TargetPlatformNeedsReflection
bool TargetPlatformNeedsReflection(TargetPlatform platform)
Definition: types.cc:126
impeller::compiler::InferShaderNameFromPath
std::string InferShaderNameFromPath(std::string_view path)
Definition: utilities.cc:18
impeller::compiler::SourceOptions::json_format
bool json_format
Definition: source_options.h:29
impeller::compiler::TargetPlatform::kMetalIOS
@ kMetalIOS
impeller::compiler::Reflector::GetReflectionCC
std::shared_ptr< fml::Mapping > GetReflectionCC() const
Definition: reflector.cc:175
switches.h
impeller::compiler::Reflector::Options::header_file_name
std::string header_file_name
Definition: reflector.h:55
impeller::compiler::Switches::reflection_cc_name
std::string reflection_cc_name
Definition: switches.h:31
impeller::compiler::Reflector::GetReflectionHeader
std::shared_ptr< fml::Mapping > GetReflectionHeader() const
Definition: reflector.cc:171
impeller::compiler::Switches::AreValid
bool AreValid(std::ostream &explain) const
Definition: switches.cc:193
impeller::compiler::Reflector::Options::target_platform
TargetPlatform target_platform
Definition: reflector.h:52
impeller::compiler::Switches::input_type
SourceType input_type
Definition: switches.h:25
impeller::compiler::Main
bool Main(const fml::CommandLine &command_line)
Definition: impellerc_main.cc:39
impeller::compiler::SourceOptions::source_language
SourceLanguage source_language
Definition: source_options.h:22
impeller::compiler::Switches::source_file_name
std::string source_file_name
Definition: switches.h:24
impeller::compiler::TargetPlatform::kVulkan
@ kVulkan
impeller::compiler::Reflector::Options::shader_name
std::string shader_name
Definition: reflector.h:54
impeller::compiler::SourceOptions::entry_point_name
std::string entry_point_name
Definition: source_options.h:26
impeller::compiler::Compiler::GetErrorMessages
std::string GetErrorMessages() const
Definition: compiler.cc:439
impeller::compiler::TargetPlatform::kRuntimeStageVulkan
@ kRuntimeStageVulkan
impeller::compiler::Compiler::GetSPIRVAssembly
std::shared_ptr< fml::Mapping > GetSPIRVAssembly() const
Definition: compiler.cc:421
impeller::compiler::Switches::spirv_file_name
std::string spirv_file_name
Definition: switches.h:28
impeller::compiler::SourceOptions::gles_language_version
uint32_t gles_language_version
Definition: source_options.h:27
impeller::compiler::Switches::source_language
SourceLanguage source_language
Definition: switches.h:35
source_options.h
impeller::compiler::EntryPointFunctionNameFromSourceName
std::string EntryPointFunctionNameFromSourceName(const std::string &file_name, SourceType type, SourceLanguage source_language, const std::string &entry_point_name)
Definition: types.cc:90
impeller::compiler::Compiler::GetReflector
const Reflector * GetReflector() const
Definition: compiler.cc:482
impeller::compiler::SourceOptions::file_name
std::string file_name
Definition: source_options.h:25
impeller::compiler::Reflector::Options
Definition: reflector.h:51
impeller::compiler::SetPermissiveAccess
static bool SetPermissiveAccess(const std::filesystem::path &p)
Definition: impellerc_main.cc:25
compiler.h
impeller::compiler::Reflector::GetRuntimeStageData
std::shared_ptr< RuntimeStageData > GetRuntimeStageData() const
Definition: reflector.cc:179
utilities.h
strings.h
impeller::compiler::SourceOptions::working_directory
std::shared_ptr< fml::UniqueFD > working_directory
Definition: source_options.h:23
impeller::compiler::SourceTypeFromFileName
SourceType SourceTypeFromFileName(const std::string &file_name)
Definition: types.cc:29
impeller::compiler::SourceOptions::target_platform
TargetPlatform target_platform
Definition: source_options.h:21
impeller::compiler::Compiler::IsValid
bool IsValid() const
Definition: compiler.cc:429
impeller::compiler::Switches::depfile_path
std::string depfile_path
Definition: switches.h:32
impeller::compiler::TargetPlatform::kOpenGLDesktop
@ kOpenGLDesktop
impeller::compiler::SourceOptions::defines
std::vector< std::string > defines
Definition: source_options.h:28
impeller::compiler::Switches::sl_file_name
std::string sl_file_name
Definition: switches.h:26
impeller::compiler::TargetPlatform::kUnknown
@ kUnknown
impeller::compiler::Switches::reflection_json_name
std::string reflection_json_name
Definition: switches.h:29
impeller::compiler::TargetPlatform::kOpenGLES
@ kOpenGLES
impeller::compiler::Compiler::GetSLShaderSource
std::shared_ptr< fml::Mapping > GetSLShaderSource() const
Definition: compiler.cc:425
main
int main(int argc, char const *argv[])
Definition: impellerc_main.cc:247
impeller::compiler::Utf8FromPath
std::string Utf8FromPath(const std::filesystem::path &path)
Converts a native format path to a utf8 string.
Definition: utilities.cc:14
impeller::compiler::TargetPlatform::kRuntimeStageMetal
@ kRuntimeStageMetal
impeller::compiler::Switches::use_half_textures
bool use_half_textures
Definition: switches.h:39
impeller::compiler::Switches::iplr
bool iplr
Definition: switches.h:27
impeller::compiler::Switches::json_format
bool json_format
Definition: switches.h:34
impeller::compiler::Reflector::GetReflectionJSON
std::shared_ptr< fml::Mapping > GetReflectionJSON() const
Definition: reflector.cc:158
impeller::compiler::Reflector::Options::entry_point_name
std::string entry_point_name
Definition: reflector.h:53
impeller::compiler::Switches::reflection_header_name
std::string reflection_header_name
Definition: switches.h:30
impeller::compiler::TargetPlatformBundlesSkSL
bool TargetPlatformBundlesSkSL(TargetPlatform platform)
Definition: types.cc:317
impeller
Definition: aiks_context.cc:10
impeller::compiler::Switches::PrintHelp
static void PrintHelp(std::ostream &stream)
Definition: switches.cc:39
types.h
impeller::compiler::TargetPlatform::kSkSL
@ kSkSL
impeller::compiler::TargetPlatform::kRuntimeStageGLES
@ kRuntimeStageGLES