| Index: mojo/public/tools/bindings/mojom_bindings_generator.py | 
| diff --git a/mojo/public/tools/bindings/mojom_bindings_generator.py b/mojo/public/tools/bindings/mojom_bindings_generator.py | 
| index 5240dd7f4d2b0660e98794b2658fa8ce624114e8..12196badfb9837b591045a366e053c607b550c3f 100755 | 
| --- a/mojo/public/tools/bindings/mojom_bindings_generator.py | 
| +++ b/mojo/public/tools/bindings/mojom_bindings_generator.py | 
| @@ -49,6 +49,7 @@ _BUILTIN_GENERATORS = { | 
| "java": "mojom_java_generator.py", | 
| } | 
|  | 
| + | 
| def LoadGenerators(generators_string): | 
| if not generators_string: | 
| return []  # No generators. | 
| @@ -77,12 +78,28 @@ def MakeImportStackMessage(imported_filename_stack): | 
| zip(imported_filename_stack[1:], imported_filename_stack)])) | 
|  | 
|  | 
| -def FindImportFile(dir_name, file_name, search_dirs): | 
| -  for search_dir in [dir_name] + search_dirs: | 
| -    path = os.path.join(search_dir, file_name) | 
| +class RelativePath(object): | 
| +  """Represents a path relative to the source tree.""" | 
| +  def __init__(self, path, source_root): | 
| +    self.path = path | 
| +    self.source_root = source_root | 
| + | 
| +  def relative_path(self): | 
| +    return os.path.relpath(os.path.abspath(self.path), | 
| +                           os.path.abspath(self.source_root)) | 
| + | 
| + | 
| +def FindImportFile(rel_dir, file_name, search_rel_dirs): | 
| +  """Finds |file_name| in either |rel_dir| or |search_rel_dirs|. Returns a | 
| +  RelativePath with first file found, or an arbitrary non-existent file | 
| +  otherwise.""" | 
| +  for rel_search_dir in [rel_dir] + search_rel_dirs: | 
| +    path = os.path.join(rel_search_dir.path, file_name) | 
| if os.path.isfile(path): | 
| -      return path | 
| -  return os.path.join(dir_name, file_name) | 
| +      return RelativePath(path, rel_search_dir.source_root) | 
| +  return RelativePath(os.path.join(rel_dir.path, file_name), | 
| +                      rel_dir.source_root) | 
| + | 
|  | 
| class MojomProcessor(object): | 
| def __init__(self, should_generate): | 
| @@ -105,18 +122,20 @@ class MojomProcessor(object): | 
| self._typemap[language] = language_map | 
|  | 
| def ProcessFile(self, args, remaining_args, generator_modules, filename): | 
| -    self._ParseFileAndImports(filename, args.import_directories, []) | 
| +    self._ParseFileAndImports(RelativePath(filename, args.depth), | 
| +                              args.import_directories, []) | 
|  | 
| return self._GenerateModule(args, remaining_args, generator_modules, | 
| -        filename) | 
| +        RelativePath(filename, args.depth)) | 
|  | 
| -  def _GenerateModule(self, args, remaining_args, generator_modules, filename): | 
| +  def _GenerateModule(self, args, remaining_args, generator_modules, | 
| +                      rel_filename): | 
| # Return the already-generated module. | 
| -    if filename in self._processed_files: | 
| -      return self._processed_files[filename] | 
| -    tree = self._parsed_files[filename] | 
| +    if rel_filename.path in self._processed_files: | 
| +      return self._processed_files[rel_filename.path] | 
| +    tree = self._parsed_files[rel_filename.path] | 
|  | 
| -    dirname, name = os.path.split(filename) | 
| +    dirname, name = os.path.split(rel_filename.path) | 
| mojom = Translate(tree, name) | 
| if args.debug_print_intermediate: | 
| pprint.PrettyPrinter().pprint(mojom) | 
| @@ -124,22 +143,21 @@ class MojomProcessor(object): | 
| # Process all our imports first and collect the module object for each. | 
| # We use these to generate proper type info. | 
| for import_data in mojom['imports']: | 
| -      import_filename = FindImportFile(dirname, | 
| -                                       import_data['filename'], | 
| -                                       args.import_directories) | 
| +      rel_import_file = FindImportFile( | 
| +          RelativePath(dirname, rel_filename.source_root), | 
| +          import_data['filename'], args.import_directories) | 
| import_data['module'] = self._GenerateModule( | 
| -          args, remaining_args, generator_modules, import_filename) | 
| +          args, remaining_args, generator_modules, rel_import_file) | 
|  | 
| module = OrderedModuleFromData(mojom) | 
|  | 
| # Set the path as relative to the source root. | 
| -    module.path = os.path.relpath(os.path.abspath(filename), | 
| -                                  os.path.abspath(args.depth)) | 
| +    module.path = rel_filename.relative_path() | 
|  | 
| # Normalize to unix-style path here to keep the generators simpler. | 
| module.path = module.path.replace('\\', '/') | 
|  | 
| -    if self._should_generate(filename): | 
| +    if self._should_generate(rel_filename.path): | 
| for language, generator_module in generator_modules.iteritems(): | 
| generator = generator_module.Generator( | 
| module, args.output_dir, typemap=self._typemap.get(language, {}), | 
| @@ -154,49 +172,56 @@ class MojomProcessor(object): | 
| generator.GenerateFiles(filtered_args) | 
|  | 
| # Save result. | 
| -    self._processed_files[filename] = module | 
| +    self._processed_files[rel_filename.path] = module | 
| return module | 
|  | 
| -  def _ParseFileAndImports(self, filename, import_directories, | 
| +  def _ParseFileAndImports(self, rel_filename, import_directories, | 
| imported_filename_stack): | 
| # Ignore already-parsed files. | 
| -    if filename in self._parsed_files: | 
| +    if rel_filename.path in self._parsed_files: | 
| return | 
|  | 
| -    if filename in imported_filename_stack: | 
| -      print "%s: Error: Circular dependency" % filename + \ | 
| -          MakeImportStackMessage(imported_filename_stack + [filename]) | 
| +    if rel_filename.path in imported_filename_stack: | 
| +      print "%s: Error: Circular dependency" % rel_filename.path + \ | 
| +          MakeImportStackMessage(imported_filename_stack + [rel_filename.path]) | 
| sys.exit(1) | 
|  | 
| try: | 
| -      with open(filename) as f: | 
| +      with open(rel_filename.path) as f: | 
| source = f.read() | 
| except IOError as e: | 
| -      print "%s: Error: %s" % (e.filename, e.strerror) + \ | 
| -          MakeImportStackMessage(imported_filename_stack + [filename]) | 
| +      print "%s: Error: %s" % (e.rel_filename.path, e.strerror) + \ | 
| +          MakeImportStackMessage(imported_filename_stack + [rel_filename.path]) | 
| sys.exit(1) | 
|  | 
| try: | 
| -      tree = Parse(source, filename) | 
| +      tree = Parse(source, rel_filename.path) | 
| except Error as e: | 
| -      full_stack = imported_filename_stack + [filename] | 
| +      full_stack = imported_filename_stack + [rel_filename.path] | 
| print str(e) + MakeImportStackMessage(full_stack) | 
| sys.exit(1) | 
|  | 
| -    dirname = os.path.split(filename)[0] | 
| +    dirname = os.path.split(rel_filename.path)[0] | 
| for imp_entry in tree.import_list: | 
| -      import_filename = FindImportFile(dirname, | 
| +      import_file_entry = FindImportFile( | 
| +          RelativePath(dirname, rel_filename.source_root), | 
| imp_entry.import_filename, import_directories) | 
| -      self._ParseFileAndImports(import_filename, import_directories, | 
| -          imported_filename_stack + [filename]) | 
| +      self._ParseFileAndImports(import_file_entry, import_directories, | 
| +          imported_filename_stack + [rel_filename.path]) | 
|  | 
| -    self._parsed_files[filename] = tree | 
| +    self._parsed_files[rel_filename.path] = tree | 
|  | 
|  | 
| def _Generate(args, remaining_args): | 
| if args.variant == "none": | 
| args.variant = None | 
|  | 
| +  for idx, import_dir in enumerate(args.import_directories): | 
| +    tokens = import_dir.split(":") | 
| +    if len(tokens) >= 2: | 
| +      args.import_directories[idx] = RelativePath(tokens[0], tokens[1]) | 
| +    else: | 
| +      args.import_directories[idx] = RelativePath(tokens[0], args.depth) | 
| generator_modules = LoadGenerators(args.generators_string) | 
|  | 
| fileutil.EnsureDirectoryExists(args.output_dir) | 
| @@ -243,7 +268,10 @@ def main(): | 
| help="comma-separated list of generators") | 
| generate_parser.add_argument( | 
| "-I", dest="import_directories", action="append", metavar="directory", | 
| -      default=[], help="add a directory to be searched for import files") | 
| +      default=[], | 
| +      help="add a directory to be searched for import files. The depth from " | 
| +           "source root can be specified for each import by appending it after " | 
| +           "a colon") | 
| generate_parser.add_argument("--typemap", action="append", metavar="TYPEMAP", | 
| default=[], dest="typemaps", | 
| help="apply TYPEMAP to generated output") | 
|  |