1 // Copyright 2015 The Shaderc Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "dependency_info.h"
16 
17 #include <fstream>
18 #include <iostream>
19 #include <sstream>
20 
21 #include "file.h"
22 #include "libshaderc_util/io.h"
23 
24 namespace glslc {
25 
DependencyInfoDumpingHandler()26 DependencyInfoDumpingHandler::DependencyInfoDumpingHandler() : mode_(not_set) {}
27 
DumpDependencyInfo(std::string compilation_output_file_name,std::string source_file_name,std::string * compilation_output_ptr,const std::unordered_set<std::string> & dependent_files)28 bool DependencyInfoDumpingHandler::DumpDependencyInfo(
29     std::string compilation_output_file_name, std::string source_file_name,
30     std::string* compilation_output_ptr,
31     const std::unordered_set<std::string>& dependent_files) {
32   std::string dep_target_label = GetTarget(compilation_output_file_name);
33   std::string dep_file_name =
34       GetDependencyFileName(compilation_output_file_name);
35 
36   // Dump everything to a string stream first, then dump its content to either
37   // a file or compilation output string, depends on current dumping mode.
38   std::stringstream dep_string_stream;
39   // dump target label and the source_file_name.
40   dep_string_stream << dep_target_label << ": " << source_file_name;
41   // dump the dependent file names.
42   for (auto& dependent_file_name : dependent_files) {
43     dep_string_stream << " " << dependent_file_name;
44   }
45   dep_string_stream << std::endl;
46 
47   if (mode_ == dump_as_compilation_output) {
48     compilation_output_ptr->assign(dep_string_stream.str());
49   } else if (mode_ == dump_as_extra_file) {
50     std::ofstream potential_file_stream_for_dep_info_dump;
51     std::ostream* dep_file_stream = shaderc_util::GetOutputStream(
52         dep_file_name, &potential_file_stream_for_dep_info_dump, &std::cerr);
53     *dep_file_stream << dep_string_stream.str();
54     if (dep_file_stream->fail()) {
55       std::cerr << "glslc: error: error writing dependent_files info to output "
56                    "file: '"
57                 << dep_file_name << "'" << std::endl;
58       return false;
59     }
60   } else {
61     // mode_ should not be 'not_set', we should never be here.
62     return false;
63   }
64   return true;
65 }
66 
GetTarget(const std::string & compilation_output_file_name)67 std::string DependencyInfoDumpingHandler::GetTarget(
68     const std::string& compilation_output_file_name) {
69   if (!user_specified_dep_target_label_.empty()) {
70     return user_specified_dep_target_label_;
71   }
72 
73   return compilation_output_file_name;
74 }
75 
GetDependencyFileName(const std::string & compilation_output_file_name)76 std::string DependencyInfoDumpingHandler::GetDependencyFileName(
77     const std::string& compilation_output_file_name) {
78   if (!user_specified_dep_file_name_.empty()) {
79     return user_specified_dep_file_name_;
80   }
81 
82   return compilation_output_file_name + ".d";
83 }
84 
IsValid(std::string * error_msg_ptr,size_t num_files)85 bool DependencyInfoDumpingHandler::IsValid(std::string* error_msg_ptr,
86                                            size_t num_files) {
87   if (DumpingModeNotSet()) {
88     *error_msg_ptr =
89         "to generate dependencies you must specify either -M (-MM) or -MD";
90     return false;
91   }
92 
93   if (!user_specified_dep_file_name_.empty() ||
94       !user_specified_dep_target_label_.empty()) {
95     if (num_files > 1) {
96       *error_msg_ptr =
97           "to specify dependency info file name or dependency info target, "
98           "only one input file is allowed.";
99       return false;
100     }
101   }
102   return true;
103 }
104 }
105