@ -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 ,