code: def add_new_target(self, address, target_type, target_base=None, dependencies=None,
                       derived_from=None, **kwargs):
      
      rel_target_base = target_base or address.spec_path
      abs_target_base = os.path.join(get_buildroot(), rel_target_base)
      if not os.path.exists(abs_target_base):
        os.makedirs(abs_target_base)
        # TODO: Adding source roots on the fly like this is yucky, but hopefully this
        # method will go away entirely under the new engine. It's primarily used for injecting
        # synthetic codegen targets, and that isn't how codegen will work in the future.
      if not self.source_roots.find_by_path(rel_target_base):
        # TODO: Set the lang and root category (source/test/thirdparty) based on the target type?
        self.source_roots.add_source_root(rel_target_base)
      if dependencies:
        dependencies = [dep.address for dep in dependencies]
  
      self.build_graph.inject_synthetic_target(address=address,
                                               target_type=target_type,
                                               dependencies=dependencies,
                                               derived_from=derived_from,
                                               **kwargs)
      new_target = self.build_graph.get_target(address)
  
      return new_target
docs: Creates a new target, adds it to the context and returns it.
  
      This method ensures the target resolves files against the given target_base, creating the
      directory if needed and registering a source root.
  
      :API: public