@Override
 public ImmutableList<String> load(@Nonnull CxxSource.Type type) {
   ImmutableList.Builder<String> builder = ImmutableList.builder();
   for (CxxPreprocessorInput input : getCxxPreprocessorInput()) {
     builder.addAll(input.getPreprocessorFlags().get(type));
   }
   return builder.build();
 }
  @Override
  public CxxPreprocessorInput getCxxPreprocessorInput(
      CxxPlatform cxxPlatform, HeaderVisibility headerVisibility)
      throws NoSuchBuildTargetException {
    CxxPreprocessorInput.Builder builder = CxxPreprocessorInput.builder();

    switch (headerVisibility) {
      case PUBLIC:
        if (Preconditions.checkNotNull(hasHeaders.apply(cxxPlatform))) {
          CxxPreprocessables.addHeaderSymlinkTree(
              builder,
              getBuildTarget(),
              ruleResolver,
              cxxPlatform.getFlavor(),
              headerVisibility,
              CxxPreprocessables.IncludeType.SYSTEM);
        }
        builder.putAllPreprocessorFlags(
            Preconditions.checkNotNull(exportedPreprocessorFlags.apply(cxxPlatform)));
        // Just pass the include dirs as system includes.
        builder.addAllSystemIncludeRoots(
            Iterables.transform(includeDirs, getProjectFilesystem().getAbsolutifier()));
        return builder.build();
      case PRIVATE:
        return builder.build();
    }

    // We explicitly don't put this in a default statement because we
    // want the compiler to warn if someone modifies the HeaderVisibility enum.
    throw new RuntimeException("Invalid header visibility: " + headerVisibility);
  }
 @Value.Lazy
 protected ImmutableList<BuildRule> getPreprocessDeps() {
   ImmutableList.Builder<BuildRule> builder = ImmutableList.builder();
   for (CxxPreprocessorInput input : getCxxPreprocessorInput()) {
     // Depend on the rules that generate the sources and headers we're compiling.
     builder.addAll(
         getPathResolver()
             .filterBuildRuleInputs(
                 ImmutableList.<SourcePath>builder()
                     .addAll(input.getIncludes().getNameToPathMap().values())
                     .build()));
     // Also add in extra deps from the preprocessor input, such as the symlink tree rules.
     builder.addAll(
         BuildRules.toBuildRulesFor(
             getParams().getBuildTarget(), getResolver(), input.getRules()));
   }
   return builder.build();
 }
  @Test
  public void nonTestLibraryDepDoesNotIncludePrivateHeadersOfLibrary() throws Exception {
    SourcePathResolver pathResolver = new SourcePathResolver(new BuildRuleResolver());

    BuildTarget libTarget = BuildTargetFactory.newInstance("//:lib");

    BuildRuleParams libParams = new FakeBuildRuleParamsBuilder(libTarget).build();
    FakeCxxLibrary libRule =
        new FakeCxxLibrary(
            libParams,
            pathResolver,
            BuildTargetFactory.newInstance("//:header"),
            BuildTargetFactory.newInstance("//:symlink"),
            Paths.get("symlink/tree/lib"),
            BuildTargetFactory.newInstance("//:privateheader"),
            BuildTargetFactory.newInstance("//:privatesymlink"),
            Paths.get("private/symlink/tree/lib"),
            new FakeBuildRule("//:archive", pathResolver),
            new FakeBuildRule("//:shared", pathResolver),
            Paths.get("output/path/lib.so"),
            "lib.so",
            // This library has no tests.
            ImmutableSortedSet.<BuildTarget>of());

    BuildTarget otherLibDepTarget = BuildTargetFactory.newInstance("//:other");
    BuildRuleParams otherLibDepParams =
        new FakeBuildRuleParamsBuilder(otherLibDepTarget)
            .setDeclaredDeps(ImmutableSortedSet.<BuildRule>of(libRule))
            .build();

    ImmutableList<CxxPreprocessorInput> otherInput =
        CxxDescriptionEnhancer.collectCxxPreprocessorInput(
            TargetGraph.EMPTY,
            otherLibDepParams,
            CxxPlatformUtils.DEFAULT_PLATFORM,
            ImmutableMultimap.<CxxSource.Type, String>of(),
            ImmutableList.<HeaderSymlinkTree>of(),
            ImmutableSet.<FrameworkPath>of(),
            CxxPreprocessables.getTransitiveCxxPreprocessorInput(
                TargetGraph.EMPTY,
                CxxPlatformUtils.DEFAULT_PLATFORM,
                FluentIterable.from(otherLibDepParams.getDeps())
                    .filter(Predicates.instanceOf(CxxPreprocessorDep.class))));

    assertThat(
        "Non-test rule with library dep should include public and not private headers",
        CxxPreprocessorInput.concat(otherInput).getIncludeRoots(),
        allOf(
            hasItem(Paths.get("symlink/tree/lib")),
            not(hasItem(Paths.get("private/symlink/tree/lib")))));
  }
  @Test
  public void libraryTestIncludesPrivateHeadersOfLibraryUnderTest() throws Exception {
    SourcePathResolver pathResolver = new SourcePathResolver(new BuildRuleResolver());

    BuildTarget libTarget = BuildTargetFactory.newInstance("//:lib");
    BuildTarget testTarget = BuildTargetFactory.newInstance("//:test");

    BuildRuleParams libParams = new FakeBuildRuleParamsBuilder(libTarget).build();
    FakeCxxLibrary libRule =
        new FakeCxxLibrary(
            libParams,
            pathResolver,
            BuildTargetFactory.newInstance("//:header"),
            BuildTargetFactory.newInstance("//:symlink"),
            Paths.get("symlink/tree/lib"),
            BuildTargetFactory.newInstance("//:privateheader"),
            BuildTargetFactory.newInstance("//:privatesymlink"),
            Paths.get("private/symlink/tree/lib"),
            new FakeBuildRule("//:archive", pathResolver),
            new FakeBuildRule("//:shared", pathResolver),
            Paths.get("output/path/lib.so"),
            "lib.so",
            // Ensure the test is listed as a dep of the lib.
            ImmutableSortedSet.of(testTarget));

    BuildRuleParams testParams =
        new FakeBuildRuleParamsBuilder(testTarget)
            .setDeclaredDeps(ImmutableSortedSet.<BuildRule>of(libRule))
            .build();

    ImmutableList<CxxPreprocessorInput> combinedInput =
        CxxDescriptionEnhancer.collectCxxPreprocessorInput(
            TargetGraph.EMPTY,
            testParams,
            CxxPlatformUtils.DEFAULT_PLATFORM,
            ImmutableMultimap.<CxxSource.Type, String>of(),
            ImmutableList.<HeaderSymlinkTree>of(),
            ImmutableSet.<FrameworkPath>of(),
            CxxPreprocessables.getTransitiveCxxPreprocessorInput(
                TargetGraph.EMPTY,
                CxxPlatformUtils.DEFAULT_PLATFORM,
                FluentIterable.from(testParams.getDeps())
                    .filter(Predicates.instanceOf(CxxPreprocessorDep.class))));

    assertThat(
        "Test of library should include both public and private headers",
        CxxPreprocessorInput.concat(combinedInput).getIncludeRoots(),
        hasItems(Paths.get("symlink/tree/lib"), Paths.get("private/symlink/tree/lib")));
  }
Exemple #6
0
 /** Builds a {@link CxxPreprocessorInput} for a rule. */
 public static CxxPreprocessorInput getCxxPreprocessorInput(
     BuildRuleParams params,
     BuildRuleResolver ruleResolver,
     Flavor flavor,
     HeaderVisibility headerVisibility,
     IncludeType includeType,
     Multimap<CxxSource.Type, String> exportedPreprocessorFlags,
     Iterable<FrameworkPath> frameworks)
     throws NoSuchBuildTargetException {
   CxxPreprocessorInput.Builder builder =
       addHeaderSymlinkTree(
           CxxPreprocessorInput.builder(),
           params.getBuildTarget(),
           ruleResolver,
           flavor,
           headerVisibility,
           includeType);
   return builder
       .putAllPreprocessorFlags(exportedPreprocessorFlags)
       .addAllFrameworks(frameworks)
       .build();
 }
  public static ImmutableList<CxxPreprocessorInput> collectCxxPreprocessorInput(
      TargetGraph targetGraph,
      BuildRuleParams params,
      CxxPlatform cxxPlatform,
      ImmutableMultimap<CxxSource.Type, String> preprocessorFlags,
      ImmutableList<HeaderSymlinkTree> headerSymlinkTrees,
      ImmutableSet<Path> frameworkSearchPaths,
      Iterable<CxxPreprocessorInput> cxxPreprocessorInputFromDeps) {

    // Add the private includes of any rules which list this rule as a test.
    BuildTarget targetWithoutFlavor =
        BuildTarget.of(params.getBuildTarget().getUnflavoredBuildTarget());
    ImmutableList.Builder<CxxPreprocessorInput> cxxPreprocessorInputFromTestedRulesBuilder =
        ImmutableList.builder();
    for (BuildRule rule : params.getDeps()) {
      if (rule instanceof NativeTestable) {
        NativeTestable testable = (NativeTestable) rule;
        if (testable.isTestedBy(targetWithoutFlavor)) {
          LOG.debug(
              "Adding private includes of tested rule %s to testing rule %s",
              rule.getBuildTarget(), params.getBuildTarget());
          cxxPreprocessorInputFromTestedRulesBuilder.add(
              testable.getCxxPreprocessorInput(targetGraph, cxxPlatform, HeaderVisibility.PRIVATE));
        }
      }
    }

    ImmutableList<CxxPreprocessorInput> cxxPreprocessorInputFromTestedRules =
        cxxPreprocessorInputFromTestedRulesBuilder.build();
    LOG.verbose(
        "Rules tested by target %s added private includes %s",
        params.getBuildTarget(), cxxPreprocessorInputFromTestedRules);

    ImmutableMap.Builder<Path, SourcePath> allLinks = ImmutableMap.builder();
    ImmutableMap.Builder<Path, SourcePath> allFullLinks = ImmutableMap.builder();
    ImmutableList.Builder<Path> allIncludeRoots = ImmutableList.builder();
    ImmutableSet.Builder<Path> allHeaderMaps = ImmutableSet.builder();
    for (HeaderSymlinkTree headerSymlinkTree : headerSymlinkTrees) {
      allLinks.putAll(headerSymlinkTree.getLinks());
      allFullLinks.putAll(headerSymlinkTree.getFullLinks());
      allIncludeRoots.add(headerSymlinkTree.getIncludePath());
      allHeaderMaps.addAll(headerSymlinkTree.getHeaderMap().asSet());
    }

    CxxPreprocessorInput localPreprocessorInput =
        CxxPreprocessorInput.builder()
            .addAllRules(Iterables.transform(headerSymlinkTrees, HasBuildTarget.TO_TARGET))
            .putAllPreprocessorFlags(preprocessorFlags)
            .setIncludes(
                CxxHeaders.builder()
                    .putAllNameToPathMap(allLinks.build())
                    .putAllFullNameToPathMap(allFullLinks.build())
                    .build())
            .addAllIncludeRoots(allIncludeRoots.build())
            .addAllHeaderMaps(allHeaderMaps.build())
            .addAllFrameworkRoots(frameworkSearchPaths)
            .build();

    return ImmutableList.<CxxPreprocessorInput>builder()
        .add(localPreprocessorInput)
        .addAll(cxxPreprocessorInputFromDeps)
        .addAll(cxxPreprocessorInputFromTestedRules)
        .build();
  }