@Override
  public <A extends Arg> BuildRule createBuildRule(
      TargetGraph targetGraph, BuildRuleParams params, BuildRuleResolver ruleResolver, A args) {

    // See if we're building a particular "type" of this library, and if so, extract
    // it as an enum.
    Optional<Map.Entry<Flavor, Type>> type;
    Optional<Map.Entry<Flavor, CxxPlatform>> platform;
    try {
      type =
          LIBRARY_TYPE.getFlavorAndValue(ImmutableSet.copyOf(params.getBuildTarget().getFlavors()));
      platform =
          cxxPlatforms.getFlavorAndValue(ImmutableSet.copyOf(params.getBuildTarget().getFlavors()));
    } catch (FlavorDomainException e) {
      throw new HumanReadableException("%s: %s", params.getBuildTarget(), e.getMessage());
    }

    // If we *are* building a specific type of this lib, call into the type specific
    // rule builder methods.  Currently, we only support building a shared lib from the
    // pre-existing static lib, which we do here.
    if (type.isPresent()) {
      Preconditions.checkState(type.get().getValue() == Type.EXTENSION);
      Preconditions.checkState(platform.isPresent());
      return createExtensionBuildRule(
          targetGraph, params, ruleResolver, platform.get().getValue(), args);
    }

    // Otherwise, we return the generic placeholder of this library, that dependents can use
    // get the real build rules via querying the action graph.
    SourcePathResolver pathResolver = new SourcePathResolver(ruleResolver);
    Path baseModule = PythonUtil.getBasePath(params.getBuildTarget(), args.baseModule);
    return new CxxPythonExtension(
        params,
        ruleResolver,
        pathResolver,
        baseModule.resolve(getExtensionName(params.getBuildTarget())));
  }
  @Override
  public <A extends Arg> BuildRule createBuildRule(
      TargetGraph targetGraph,
      final BuildRuleParams params,
      final BuildRuleResolver ruleResolver,
      final A args)
      throws NoSuchBuildTargetException {

    // See if we're building a particular "type" of this library, and if so, extract
    // it as an enum.
    final Optional<Map.Entry<Flavor, Type>> type =
        LIBRARY_TYPE.getFlavorAndValue(params.getBuildTarget());
    Optional<Map.Entry<Flavor, CxxPlatform>> platform =
        cxxPlatforms.getFlavorAndValue(params.getBuildTarget());
    final Optional<Map.Entry<Flavor, PythonPlatform>> pythonPlatform =
        pythonPlatforms.getFlavorAndValue(params.getBuildTarget());

    // If we *are* building a specific type of this lib, call into the type specific
    // rule builder methods.  Currently, we only support building a shared lib from the
    // pre-existing static lib, which we do here.
    if (type.isPresent() && platform.isPresent() && pythonPlatform.isPresent()) {
      Preconditions.checkState(type.get().getValue() == Type.EXTENSION);
      return createExtensionBuildRule(
          params.copyWithDeps(
              Suppliers.ofInstance(
                  ImmutableSortedSet.copyOf(
                      getPlatformDeps(
                          params, ruleResolver, pythonPlatform.get().getValue(), args))),
              Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of())),
          ruleResolver,
          pythonPlatform.get().getValue(),
          platform.get().getValue(),
          args);
    }

    // Otherwise, we return the generic placeholder of this library, that dependents can use
    // get the real build rules via querying the action graph.
    final SourcePathResolver pathResolver = new SourcePathResolver(ruleResolver);
    Path baseModule = PythonUtil.getBasePath(params.getBuildTarget(), args.baseModule);
    final Path module = baseModule.resolve(getExtensionName(params.getBuildTarget()));
    return new CxxPythonExtension(params, pathResolver) {

      @Override
      protected BuildRule getExtension(PythonPlatform pythonPlatform, CxxPlatform cxxPlatform)
          throws NoSuchBuildTargetException {
        return ruleResolver.requireRule(
            getBuildTarget()
                .withFlavors(
                    pythonPlatform.getFlavor(),
                    cxxPlatform.getFlavor(),
                    CxxDescriptionEnhancer.SHARED_FLAVOR));
      }

      @Override
      public Path getModule() {
        return module;
      }

      @Override
      public PythonPackageComponents getPythonPackageComponents(
          PythonPlatform pythonPlatform, CxxPlatform cxxPlatform)
          throws NoSuchBuildTargetException {
        BuildRule extension = getExtension(pythonPlatform, cxxPlatform);
        SourcePath output = new BuildTargetSourcePath(extension.getBuildTarget());
        return PythonPackageComponents.of(
            ImmutableMap.of(module, output),
            ImmutableMap.<Path, SourcePath>of(),
            ImmutableMap.<Path, SourcePath>of(),
            ImmutableSet.<SourcePath>of(),
            Optional.of(false));
      }

      @Override
      public SharedNativeLinkTarget getNativeLinkTarget(final PythonPlatform pythonPlatform) {
        return new SharedNativeLinkTarget() {

          @Override
          public BuildTarget getBuildTarget() {
            return params.getBuildTarget().withAppendedFlavors(pythonPlatform.getFlavor());
          }

          @Override
          public Iterable<? extends NativeLinkable> getSharedNativeLinkTargetDeps(
              CxxPlatform cxxPlatform) {
            return FluentIterable.from(getPlatformDeps(params, ruleResolver, pythonPlatform, args))
                .filter(NativeLinkable.class);
          }

          @Override
          public Optional<String> getSharedNativeLinkTargetLibraryName(CxxPlatform cxxPlatform) {
            return Optional.absent();
          }

          @Override
          public NativeLinkableInput getSharedNativeLinkTargetInput(CxxPlatform cxxPlatform)
              throws NoSuchBuildTargetException {
            return NativeLinkableInput.builder()
                .addAllArgs(
                    getExtensionArgs(
                        params.copyWithChanges(
                            params
                                .getBuildTarget()
                                .withAppendedFlavors(
                                    pythonPlatform.getFlavor(),
                                    CxxDescriptionEnhancer.SHARED_FLAVOR),
                            Suppliers.ofInstance(
                                ImmutableSortedSet.copyOf(
                                    getPlatformDeps(params, ruleResolver, pythonPlatform, args))),
                            Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of())),
                        ruleResolver,
                        pathResolver,
                        cxxPlatform,
                        args))
                .addAllFrameworks(args.frameworks.or(ImmutableSortedSet.<FrameworkPath>of()))
                .build();
          }
        };
      }

      @Override
      public ImmutableSortedSet<BuildRule> getRuntimeDeps() {
        return getDeclaredDeps();
      }
    };
  }