|
|
@@ -46,6 +46,7 @@
|
|
|
#endif
|
|
|
#include <errno.h>
|
|
|
#include <iostream>
|
|
|
+#include <sstream>
|
|
|
#include <ctype.h>
|
|
|
|
|
|
#include <google/protobuf/stubs/hash.h>
|
|
|
@@ -725,6 +726,12 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ if (!manifest_name_.empty()) {
|
|
|
+ if (!GenerateDependencyManifestFile(parsed_files, &source_tree)) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
if (mode_ == MODE_ENCODE || mode_ == MODE_DECODE) {
|
|
|
if (codec_type_.empty()) {
|
|
|
// HACK: Define an EmptyMessage type to use for decoding.
|
|
|
@@ -775,6 +782,7 @@ void CommandLineInterface::Clear() {
|
|
|
output_directives_.clear();
|
|
|
codec_type_.clear();
|
|
|
descriptor_set_name_.clear();
|
|
|
+ manifest_name_.clear();
|
|
|
|
|
|
mode_ = MODE_COMPILE;
|
|
|
print_mode_ = PRINT_NONE;
|
|
|
@@ -1012,6 +1020,22 @@ CommandLineInterface::InterpretArgument(const string& name,
|
|
|
}
|
|
|
descriptor_set_name_ = value;
|
|
|
|
|
|
+ } else if (name == "--manifest-file") {
|
|
|
+ if (!manifest_name_.empty()) {
|
|
|
+ cerr << name << " may only be passed once." << endl;
|
|
|
+ return PARSE_ARGUMENT_FAIL;
|
|
|
+ }
|
|
|
+ if (value.empty()) {
|
|
|
+ cerr << name << " requires a non-empty value." << endl;
|
|
|
+ return PARSE_ARGUMENT_FAIL;
|
|
|
+ }
|
|
|
+ if (mode_ != MODE_COMPILE) {
|
|
|
+ cerr << "Cannot use --encode or --decode and generate a manifest at the "
|
|
|
+ "same time." << endl;
|
|
|
+ return PARSE_ARGUMENT_FAIL;
|
|
|
+ }
|
|
|
+ manifest_name_ = value;
|
|
|
+
|
|
|
} else if (name == "--include_imports") {
|
|
|
if (imports_in_descriptor_set_) {
|
|
|
cerr << name << " may only be passed once." << endl;
|
|
|
@@ -1206,6 +1230,9 @@ void CommandLineInterface::PrintHelpText() {
|
|
|
" include information about the original\n"
|
|
|
" location of each decl in the source file as\n"
|
|
|
" well as surrounding comments.\n"
|
|
|
+" --manifest_file=FILE Write a dependency output file in the format\n"
|
|
|
+" expected by make. This writes the transitive\n"
|
|
|
+" set of input file paths to FILE\n"
|
|
|
" --error_format=FORMAT Set the format in which to print errors.\n"
|
|
|
" FORMAT may be 'gcc' (the default) or 'msvs'\n"
|
|
|
" (Microsoft Visual Studio format).\n"
|
|
|
@@ -1282,6 +1309,62 @@ bool CommandLineInterface::GenerateOutput(
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+bool CommandLineInterface::GenerateDependencyManifestFile(
|
|
|
+ const vector<const FileDescriptor*> parsed_files,
|
|
|
+ DiskSourceTree * source_tree) {
|
|
|
+ FileDescriptorSet file_set;
|
|
|
+
|
|
|
+ set<const FileDescriptor*> already_seen;
|
|
|
+ for (int i = 0; i < parsed_files.size(); i++) {
|
|
|
+ GetTransitiveDependencies(parsed_files[i],
|
|
|
+ false,
|
|
|
+ &already_seen, file_set.mutable_file());
|
|
|
+ }
|
|
|
+
|
|
|
+ int fd;
|
|
|
+ do {
|
|
|
+ fd = open(manifest_name_.c_str(),
|
|
|
+ O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
|
|
|
+ } while (fd < 0 && errno == EINTR);
|
|
|
+
|
|
|
+ if (fd < 0) {
|
|
|
+ perror(manifest_name_.c_str());
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ stringstream ss;
|
|
|
+ string output_filename = manifest_name_;
|
|
|
+ if (output_filename.compare(0, 2, "./") == 0) {
|
|
|
+ output_filename = output_filename.substr(2);
|
|
|
+ }
|
|
|
+ ss << output_filename << ": ";
|
|
|
+ for (set<const FileDescriptor*>::const_iterator it = already_seen.begin(); it != already_seen.end(); ++it ) {
|
|
|
+ string virtual_file = (*it)->name();
|
|
|
+ string disk_file;
|
|
|
+ if (source_tree && source_tree->VirtualFileToDiskFile(virtual_file, &disk_file) ) {
|
|
|
+ ss << " " << disk_file << " \\" << endl;
|
|
|
+ } else {
|
|
|
+ cerr << "Unable to identify path for file " << virtual_file << endl;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ string manifest_contents = ss.str();
|
|
|
+ if ( write(fd, manifest_contents.c_str(), manifest_contents.size()) != manifest_contents.size() ) {
|
|
|
+ cerr << "Error when writing to " << manifest_name_ << endl;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ int rv = ::close(fd);
|
|
|
+ if ( rv != 0 ) {
|
|
|
+ cerr << manifest_name_ << ": " << strerror(rv) << endl;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
bool CommandLineInterface::GeneratePluginOutput(
|
|
|
const vector<const FileDescriptor*>& parsed_files,
|
|
|
const string& plugin_name,
|