Example #1
0
  private void createHeaderAction(
      String outputName,
      Builder result,
      AnalysisEnvironment env,
      CppCompileActionBuilder builder,
      boolean generateDotd) {
    String outputNameBase =
        CppHelper.getCompileArtifactName(
            ruleContext, ArtifactCategory.GENERATED_HEADER, outputName);

    builder
        .setOutputs(ArtifactCategory.PROCESSED_HEADER, outputNameBase, generateDotd)
        // If we generate pic actions, we prefer the header actions to use the pic artifacts.
        .setPicMode(this.getGeneratePicActions());
    setupCompileBuildVariables(
        builder,
        this.getGeneratePicActions(),
        /*ccRelativeName=*/ null,
        /*autoFdoImportPath=*/ null,
        /*gcnoFile=*/ null,
        /*dwoFile=*/ null,
        ImmutableMap.<String, String>of());
    semantics.finalizeCompileActionBuilder(ruleContext, builder);
    CppCompileAction compileAction = builder.build();
    env.registerAction(compileAction);
    Artifact tokenFile = compileAction.getOutputFile();
    result.addHeaderTokenFile(tokenFile);
  }
 @Test
 public void testIncludePathOrder() throws Exception {
   scratch.file(
       "foo/BUILD",
       "cc_library(",
       "    name = 'bar',",
       "    includes = ['bar'],",
       ")",
       "cc_library(",
       "    name = 'foo',",
       "    srcs = ['foo.cc'],",
       "    includes = ['foo'],",
       "    deps = [':bar'],",
       ")");
   ConfiguredTarget target = getConfiguredTarget("//foo");
   CppCompileAction action = getCppCompileAction(target);
   String genfilesDir = target.getConfiguration().getGenfilesFragment().toString();
   // Local include paths come first.
   assertContainsSublist(
       action.getCompilerOptions(),
       ImmutableList.of(
           "-isystem",
           "foo/foo",
           "-isystem",
           genfilesDir + "/foo/foo",
           "-isystem",
           "foo/bar",
           "-isystem",
           genfilesDir + "/foo/bar",
           "-isystem",
           TestConstants.GCC_INCLUDE_PATH));
 }
 @Test
 public void testDisablingHeaderModulesWhenDependingOnModuleBuildTransitively() throws Exception {
   AnalysisMock.get()
       .ccSupport()
       .setupCrosstool(mockToolsConfig, MockCcSupport.HEADER_MODULES_FEATURE_CONFIGURATION);
   useConfiguration();
   scratch.file(
       "module/BUILD",
       "package(features = ['header_modules'])",
       "cc_library(",
       "    name = 'module',",
       "    srcs = ['a.cc', 'a.h'],",
       ")");
   scratch.file(
       "nomodule/BUILD",
       "package(features = ['-header_modules'])",
       "cc_library(",
       "    name = 'nomodule',",
       "    srcs = ['a.cc', 'a.h'],",
       "    deps = ['//module']",
       ")");
   CppCompileAction moduleAction = getCppCompileAction("//module:module");
   assertThat(moduleAction.getCompilerOptions()).contains("module_name://module:module");
   CppCompileAction noModuleAction = getCppCompileAction("//nomodule:nomodule");
   assertThat(noModuleAction.getCompilerOptions()).doesNotContain("module_name://module:module");
 }
 private List<String> getCompilationModeFlags(String... flags) throws Exception {
   AnalysisMock.get().ccSupport().setupCrosstool(mockToolsConfig, COMPILATION_MODE_FEATURES);
   useConfiguration(flags);
   scratch.overwriteFile("mode/BUILD", "cc_library(name = 'a', srcs = ['a.cc'])");
   getConfiguredTarget("//mode:a");
   Artifact objectArtifact = getBinArtifact("_objs/a/mode/a.pic.o", "//mode:a");
   CppCompileAction action = (CppCompileAction) getGeneratingAction(objectArtifact);
   return action.getCompilerOptions();
 }
Example #5
0
  /** Create the actions for "--save_temps". */
  private ImmutableList<Artifact> createTempsActions(
      Artifact source,
      String outputName,
      CppCompileActionBuilder builder,
      boolean usePic,
      boolean generateDotd,
      PathFragment ccRelativeName) {
    if (!cppConfiguration.getSaveTemps()) {
      return ImmutableList.of();
    }

    String path = source.getFilename();
    boolean isCFile = CppFileTypes.C_SOURCE.matches(path);
    boolean isCppFile = CppFileTypes.CPP_SOURCE.matches(path);

    if (!isCFile && !isCppFile) {
      return ImmutableList.of();
    }

    ArtifactCategory category =
        isCFile ? ArtifactCategory.PREPROCESSED_C_SOURCE : ArtifactCategory.PREPROCESSED_CPP_SOURCE;

    String outputArtifactNameBase = getOutputNameBaseWith(outputName, usePic);

    CppCompileActionBuilder dBuilder = new CppCompileActionBuilder(builder);
    dBuilder.setOutputs(category, outputArtifactNameBase, generateDotd);
    setupCompileBuildVariables(
        dBuilder,
        usePic,
        ccRelativeName,
        source.getExecPath(),
        null,
        null,
        ImmutableMap.<String, String>of());
    semantics.finalizeCompileActionBuilder(ruleContext, dBuilder);
    CppCompileAction dAction = dBuilder.build();
    ruleContext.registerAction(dAction);

    CppCompileActionBuilder sdBuilder = new CppCompileActionBuilder(builder);
    sdBuilder.setOutputs(ArtifactCategory.GENERATED_ASSEMBLY, outputArtifactNameBase, generateDotd);
    setupCompileBuildVariables(
        sdBuilder,
        usePic,
        ccRelativeName,
        source.getExecPath(),
        null,
        null,
        ImmutableMap.<String, String>of());
    semantics.finalizeCompileActionBuilder(ruleContext, sdBuilder);
    CppCompileAction sdAction = sdBuilder.build();
    ruleContext.registerAction(sdAction);

    return ImmutableList.of(dAction.getOutputFile(), sdAction.getOutputFile());
  }
 @Test
 public void testTopLevelHeaderModules() throws Exception {
   AnalysisMock.get()
       .ccSupport()
       .setupCrosstool(
           mockToolsConfig,
           MockCcSupport.HEADER_MODULES_FEATURE_CONFIGURATION
               + "feature { name: 'header_module_includes_dependencies' }");
   useConfiguration();
   setupPackagesForModuleTests(/*useHeaderModules=*/ false);
   getConfiguredTarget("//module:j");
   Artifact jObjectArtifact = getBinArtifact("_objs/j/module/j.pic.o", "//module:j");
   CppCompileAction jObjectAction = (CppCompileAction) getGeneratingAction(jObjectArtifact);
   assertThat(getHeaderModuleFlags(jObjectAction.getCompilerOptions()))
       .containsExactly("g.pic.pcm");
 }
Example #7
0
  private void createFakeSourceAction(
      String outputName,
      CcCompilationOutputs.Builder result,
      AnalysisEnvironment env,
      CppCompileActionBuilder builder,
      ArtifactCategory outputCategory,
      boolean addObject,
      PathFragment ccRelativeName,
      PathFragment execPath,
      boolean usePic,
      boolean generateDotd) {
    String outputNameBase = getOutputNameBaseWith(outputName, usePic);
    String tempOutputName =
        ruleContext
            .getConfiguration()
            .getBinFragment()
            .getRelative(CppHelper.getObjDirectory(ruleContext.getLabel()))
            .getRelative(
                CppHelper.getCompileArtifactName(
                    ruleContext,
                    outputCategory,
                    getOutputNameBaseWith(outputName + ".temp", usePic)))
            .getPathString();
    builder
        .setPicMode(usePic)
        .setOutputs(outputCategory, outputNameBase, generateDotd)
        .setTempOutputFile(new PathFragment(tempOutputName));

    setupCompileBuildVariables(
        builder,
        usePic,
        ccRelativeName,
        execPath,
        /*gcnoFile=*/ null,
        /*dwoFile=*/ null,
        ImmutableMap.<String, String>of());
    semantics.finalizeCompileActionBuilder(ruleContext, builder);
    CppCompileAction action = builder.build();
    env.registerAction(action);
    if (addObject) {
      if (usePic) {
        result.addPicObjectFile(action.getOutputFile());
      } else {
        result.addObjectFile(action.getOutputFile());
      }
    }
  }
 @Test
 public void testDefinesOrder() throws Exception {
   scratch.file(
       "foo/BUILD",
       "cc_library(",
       "    name = 'bar',",
       "    defines = ['BAR'],",
       ")",
       "cc_library(",
       "    name = 'foo',",
       "    srcs = ['foo.cc'],",
       "    defines = ['FOO'],",
       "    deps = [':bar'],",
       ")");
   CppCompileAction action = getCppCompileAction("//foo");
   // Inherited defines come first.
   assertContainsSublist(action.getCompilerOptions(), ImmutableList.of("-DBAR", "-DFOO"));
 }
  @Test
  public void testCompileUsingHeaderModulesTransitivelyWithTranstiveModuleMaps() throws Exception {
    AnalysisMock.get()
        .ccSupport()
        .setupCrosstool(
            mockToolsConfig,
            MockCcSupport.HEADER_MODULES_FEATURE_CONFIGURATION
                + "feature { name: 'transitive_module_maps' }");
    useConfiguration("--features=transitive_module_maps");
    setupPackagesForModuleTests(/*useHeaderModules=*/ true);

    getConfiguredTarget("//nomodule:f");
    Artifact fObjectArtifact = getBinArtifact("_objs/f/nomodule/f.pic.o", "//nomodule:f");
    CppCompileAction fObjectAction = (CppCompileAction) getGeneratingAction(fObjectArtifact);
    // Only the module map of f itself itself and the direct dependencies are needed.
    assertThat(getNonSystemModuleMaps(fObjectAction.getInputs()))
        .containsExactly(
            getGenfilesArtifact("y.cppmap", "//nomodule:y"),
            getGenfilesArtifact("z.cppmap", "//nomodule:z"),
            getGenfilesArtifact("a.cppmap", "//nomodule:a"),
            getGenfilesArtifact("f.cppmap", "//nomodule:f"),
            getGenfilesArtifact("e.cppmap", "//nomodule:e"));

    getConfiguredTarget("//nomodule:c");
    Artifact cObjectArtifact = getBinArtifact("_objs/c/nomodule/c.pic.o", "//nomodule:c");
    CppCompileAction cObjectAction = (CppCompileAction) getGeneratingAction(cObjectArtifact);
    assertThat(getNonSystemModuleMaps(cObjectAction.getInputs()))
        .containsExactly(
            getGenfilesArtifact("y.cppmap", "//nomodule:y"),
            getGenfilesArtifact("z.cppmap", "//nomodule:z"),
            getGenfilesArtifact("a.cppmap", "//nomodule:a"),
            getGenfilesArtifact("b.cppmap", "//module:b"),
            getGenfilesArtifact("c.cppmap", "//nomodule:e"));
    assertThat(getHeaderModuleFlags(cObjectAction.getCompilerOptions()))
        .containsExactly("b.pic.pcm");

    getConfiguredTarget("//nomodule:d");
    Artifact dObjectArtifact = getBinArtifact("_objs/d/nomodule/d.pic.o", "//nomodule:d");
    CppCompileAction dObjectAction = (CppCompileAction) getGeneratingAction(dObjectArtifact);
    assertThat(getNonSystemModuleMaps(dObjectAction.getInputs()))
        .containsExactly(
            getGenfilesArtifact("y.cppmap", "//nomodule:y"),
            getGenfilesArtifact("z.cppmap", "//nomodule:z"),
            getGenfilesArtifact("a.cppmap", "//nomodule:a"),
            getGenfilesArtifact("b.cppmap", "//module:b"),
            getGenfilesArtifact("c.cppmap", "//nomodule:c"),
            getGenfilesArtifact("d.cppmap", "//nomodule:d"));
    assertThat(getHeaderModuleFlags(dObjectAction.getCompilerOptions()))
        .containsExactly("b.pic.pcm");
  }
  @Test
  public void testCompileHeaderModules() throws Exception {
    AnalysisMock.get()
        .ccSupport()
        .setupCrosstool(
            mockToolsConfig,
            "" + "feature { name: 'header_modules' }" + "feature { name: 'module_maps' }");
    useConfiguration();
    scratch.file(
        "module/BUILD",
        "package(features = ['header_modules'])",
        "cc_library(",
        "    name = 'a',",
        "    srcs = ['a.h', 'a.cc'],",
        "    deps = ['b']",
        ")",
        "cc_library(",
        "    name = 'b',",
        "    srcs = ['b.h'],",
        "    textual_hdrs = ['t.h'],",
        ")");
    getConfiguredTarget("//module:b");
    Artifact bModuleArtifact = getBinArtifact("_objs/b/module/b.pic.pcm", "//module:b");
    CppCompileAction bModuleAction = (CppCompileAction) getGeneratingAction(bModuleArtifact);
    assertThat(bModuleAction.getIncludeScannerSources())
        .containsExactly(getSourceArtifact("module/b.h"), getSourceArtifact("module/t.h"));
    assertThat(bModuleAction.getInputs())
        .contains(getGenfilesArtifactWithNoOwner("module/b.cppmap"));

    getConfiguredTarget("//module:a");
    Artifact aObjectArtifact = getBinArtifact("_objs/a/module/a.pic.o", "//module:a");
    CppCompileAction aObjectAction = (CppCompileAction) getGeneratingAction(aObjectArtifact);
    assertThat(aObjectAction.getIncludeScannerSources())
        .containsExactly(
            getSourceArtifact("module/a.cc"),
            getSourceArtifact("module/b.h"),
            getSourceArtifact("module/t.h"));
    assertThat(aObjectAction.getInputs())
        .contains(getBinArtifact("_objs/b/module/b.pic.pcm", "//module:b"));
    assertThat(aObjectAction.getInputs())
        .contains(getGenfilesArtifactWithNoOwner("module/b.cppmap"));
    assertNoEvents();
  }
Example #11
0
  private void createSourceAction(
      String outputName,
      CcCompilationOutputs.Builder result,
      AnalysisEnvironment env,
      Artifact sourceArtifact,
      CppCompileActionBuilder builder,
      ArtifactCategory outputCategory,
      boolean addObject,
      boolean enableCoverage,
      boolean generateDwo,
      boolean generateDotd,
      Map<String, String> sourceSpecificBuildVariables) {
    PathFragment ccRelativeName = semantics.getEffectiveSourcePath(sourceArtifact);
    if (cppConfiguration.isLipoOptimization()) {
      // TODO(bazel-team): we shouldn't be needing this, merging context with the binary
      // is a superset of necessary information.
      LipoContextProvider lipoProvider =
          Preconditions.checkNotNull(CppHelper.getLipoContextProvider(ruleContext), outputName);
      builder.setContext(
          CppCompilationContext.mergeForLipo(lipoProvider.getLipoContext(), context));
    }

    boolean generatePicAction = getGeneratePicActions();
    // If we always need pic for everything, then don't bother to create a no-pic action.
    boolean generateNoPicAction = getGenerateNoPicActions();
    Preconditions.checkState(generatePicAction || generateNoPicAction);
    if (fake) {
      boolean usePic = !generateNoPicAction;
      createFakeSourceAction(
          outputName,
          result,
          env,
          builder,
          outputCategory,
          addObject,
          ccRelativeName,
          sourceArtifact.getExecPath(),
          usePic,
          generateDotd);
    } else {
      // Create PIC compile actions (same as non-PIC, but use -fPIC and
      // generate .pic.o, .pic.d, .pic.gcno instead of .o, .d, .gcno.)
      if (generatePicAction) {
        String picOutputBase =
            CppHelper.getCompileArtifactName(ruleContext, ArtifactCategory.PIC_FILE, outputName);
        CppCompileActionBuilder picBuilder =
            copyAsPicBuilder(builder, picOutputBase, outputCategory, generateDotd);
        String gcnoFileName =
            CppHelper.getCompileArtifactName(
                ruleContext, ArtifactCategory.COVERAGE_DATA_FILE, picOutputBase);
        Artifact gcnoFile =
            enableCoverage ? CppHelper.getCompileOutputArtifact(ruleContext, gcnoFileName) : null;
        Artifact dwoFile = generateDwo ? getDwoFile(picBuilder.getOutputFile()) : null;

        setupCompileBuildVariables(
            picBuilder,
            /*usePic=*/ true,
            ccRelativeName,
            sourceArtifact.getExecPath(),
            gcnoFile,
            dwoFile,
            sourceSpecificBuildVariables);

        if (maySaveTemps) {
          result.addTemps(
              createTempsActions(
                  sourceArtifact,
                  outputName,
                  picBuilder,
                  /*usePic=*/ true,
                  /*generateDotd=*/ generateDotd,
                  ccRelativeName));
        }

        picBuilder.setGcnoFile(gcnoFile);
        picBuilder.setDwoFile(dwoFile);

        semantics.finalizeCompileActionBuilder(ruleContext, picBuilder);
        CppCompileAction picAction = picBuilder.build();
        env.registerAction(picAction);
        if (addObject) {
          result.addPicObjectFile(picAction.getOutputFile());

          if (featureConfiguration.isEnabled(CppRuleClasses.THIN_LTO)
              && CppFileTypes.LTO_SOURCE.matches(sourceArtifact.getFilename())) {
            result.addLTOBitcodeFile(picAction.getOutputFile());
          }
        }
        if (dwoFile != null) {
          // Host targets don't produce .dwo files.
          result.addPicDwoFile(dwoFile);
        }
        if (cppConfiguration.isLipoContextCollector() && !generateNoPicAction) {
          result.addLipoScannable(picAction);
        }
      }

      if (generateNoPicAction) {
        Artifact noPicOutputFile =
            CppHelper.getCompileOutputArtifact(
                ruleContext,
                CppHelper.getCompileArtifactName(ruleContext, outputCategory, outputName));
        builder.setOutputs(outputCategory, outputName, generateDotd);
        String gcnoFileName =
            CppHelper.getCompileArtifactName(
                ruleContext, ArtifactCategory.COVERAGE_DATA_FILE, outputName);

        // Create non-PIC compile actions
        Artifact gcnoFile =
            !cppConfiguration.isLipoOptimization() && enableCoverage
                ? CppHelper.getCompileOutputArtifact(ruleContext, gcnoFileName)
                : null;

        Artifact noPicDwoFile = generateDwo ? getDwoFile(noPicOutputFile) : null;

        setupCompileBuildVariables(
            builder,
            /*usePic=*/ false,
            ccRelativeName,
            sourceArtifact.getExecPath(),
            gcnoFile,
            noPicDwoFile,
            sourceSpecificBuildVariables);

        if (maySaveTemps) {
          result.addTemps(
              createTempsActions(
                  sourceArtifact,
                  outputName,
                  builder,
                  /*usePic=*/ false,
                  /*generateDotd*/ generateDotd,
                  ccRelativeName));
        }

        builder.setGcnoFile(gcnoFile);
        builder.setDwoFile(noPicDwoFile);

        semantics.finalizeCompileActionBuilder(ruleContext, builder);
        CppCompileAction compileAction = builder.build();
        env.registerAction(compileAction);
        Artifact objectFile = compileAction.getOutputFile();
        if (addObject) {
          result.addObjectFile(objectFile);
          if (featureConfiguration.isEnabled(CppRuleClasses.THIN_LTO)
              && CppFileTypes.LTO_SOURCE.matches(sourceArtifact.getFilename())) {
            result.addLTOBitcodeFile(objectFile);
          }
        }
        if (noPicDwoFile != null) {
          // Host targets don't produce .dwo files.
          result.addDwoFile(noPicDwoFile);
        }
        if (cppConfiguration.isLipoContextCollector()) {
          result.addLipoScannable(compileAction);
        }
      }
    }
  }
  @Test
  public void testCompileHeaderModulesTransitively() throws Exception {
    AnalysisMock.get()
        .ccSupport()
        .setupCrosstool(mockToolsConfig, MockCcSupport.HEADER_MODULES_FEATURE_CONFIGURATION);
    useConfiguration();
    setupPackagesForModuleTests(/*useHeaderModules=*/ false);

    // The //nomodule:f target only depends on non-module targets, thus it should be module-free.
    getConfiguredTarget("//nomodule:f");
    assertThat(getGeneratingAction(getBinArtifact("_objs/f/nomodule/f.pic.pcm", "//nomodule:f")))
        .isNull();
    Artifact fObjectArtifact = getBinArtifact("_objs/f/nomodule/f.pic.o", "//nomodule:f");
    CppCompileAction fObjectAction = (CppCompileAction) getGeneratingAction(fObjectArtifact);
    // Only the module map of f itself itself and the direct dependencies are needed.
    assertThat(getNonSystemModuleMaps(fObjectAction.getInputs()))
        .containsExactly(
            getGenfilesArtifact("f.cppmap", "//nomodule:f"),
            getGenfilesArtifact("e.cppmap", "//nomodule:e"));
    assertThat(getHeaderModules(fObjectAction.getInputs())).isEmpty();
    assertThat(fObjectAction.getIncludeScannerSources())
        .containsExactly(getSourceArtifact("nomodule/f.cc"));
    assertThat(getHeaderModuleFlags(fObjectAction.getCompilerOptions())).isEmpty();

    // The //nomodule:c target will get the header module for //module:b, which is a direct
    // dependency.
    getConfiguredTarget("//nomodule:c");
    assertThat(getGeneratingAction(getBinArtifact("_objs/c/nomodule/c.pic.pcm", "//nomodule:c")))
        .isNull();
    Artifact cObjectArtifact = getBinArtifact("_objs/c/nomodule/c.pic.o", "//nomodule:c");
    CppCompileAction cObjectAction = (CppCompileAction) getGeneratingAction(cObjectArtifact);
    assertThat(getNonSystemModuleMaps(cObjectAction.getInputs()))
        .containsExactly(
            getGenfilesArtifact("b.cppmap", "//module:b"),
            getGenfilesArtifact("c.cppmap", "//nomodule:e"));
    assertThat(getHeaderModules(cObjectAction.getInputs()))
        .containsExactly(getBinArtifact("_objs/b/module/b.pic.pcm", "//module:b"));
    // All headers of transitive dependencies that are built as modules are needed as entry points
    // for include scanning.
    assertThat(cObjectAction.getIncludeScannerSources())
        .containsExactly(getSourceArtifact("nomodule/c.cc"), getSourceArtifact("module/b.h"));
    assertThat(cObjectAction.getMainIncludeScannerSource())
        .isEqualTo(getSourceArtifact("nomodule/c.cc"));
    assertThat(getHeaderModuleFlags(cObjectAction.getCompilerOptions())).isEmpty();

    // The //nomodule:d target depends on //module:b via one indirection (//nomodule:c).
    getConfiguredTarget("//nomodule:d");
    assertThat(getGeneratingAction(getBinArtifact("_objs/d/nomodule/d.pic.pcm", "//nomodule:d")))
        .isNull();
    Artifact dObjectArtifact = getBinArtifact("_objs/d/nomodule/d.pic.o", "//nomodule:d");
    CppCompileAction dObjectAction = (CppCompileAction) getGeneratingAction(dObjectArtifact);
    // Module map 'c.cppmap' is needed because it is a direct dependency.
    assertThat(getNonSystemModuleMaps(dObjectAction.getInputs()))
        .containsExactly(
            getGenfilesArtifact("c.cppmap", "//nomodule:c"),
            getGenfilesArtifact("d.cppmap", "//nomodule:d"));
    assertThat(getHeaderModules(dObjectAction.getInputs()))
        .containsExactly(getBinArtifact("_objs/b/module/b.pic.pcm", "//module:b"));
    // All headers of transitive dependencies that are built as modules are needed as entry points
    // for include scanning.
    assertThat(dObjectAction.getIncludeScannerSources())
        .containsExactly(getSourceArtifact("module/b.h"), getSourceArtifact("nomodule/d.cc"));
    assertThat(getHeaderModuleFlags(dObjectAction.getCompilerOptions())).isEmpty();

    // The //module:j target depends on //module:g via //nomodule:h and on //module:b via
    // both //module:g and //nomodule:c.
    getConfiguredTarget("//module:j");
    Artifact jObjectArtifact = getBinArtifact("_objs/j/module/j.pic.o", "//module:j");
    CppCompileAction jObjectAction = (CppCompileAction) getGeneratingAction(jObjectArtifact);
    assertThat(getHeaderModules(jObjectAction.getInputs()))
        .containsExactly(
            getBinArtifact("_objs/b/module/b.pic.pcm", "//module:b"),
            getBinArtifact("_objs/g/module/g.pic.pcm", "//module:g"));
    assertThat(jObjectAction.getIncludeScannerSources())
        .containsExactly(
            getSourceArtifact("module/j.cc"),
            getSourceArtifact("module/b.h"),
            getSourceArtifact("module/g.h"));
    assertThat(jObjectAction.getMainIncludeScannerSource())
        .isEqualTo(getSourceArtifact("module/j.cc"));
    assertThat(getHeaderModuleFlags(jObjectAction.getCompilerOptions()))
        .containsExactly("b.pic.pcm", "g.pic.pcm");
  }