@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(); }
@Test public void testNoCppModuleMap() throws Exception { AnalysisMock.get() .ccSupport() .setupCrosstool(mockToolsConfig, "feature { name: 'no_legacy_features' }"); useConfiguration(); writeSimpleCcLibrary(); assertNoCppModuleMapAction("//module:map"); }
@Test public void testDoNotCompileSourceFilesInHeaders() throws Exception { AnalysisMock.get() .ccSupport() .setupCrosstool(mockToolsConfig, MockCcSupport.HEADER_PROCESSING_FEATURE_CONFIGURATION); useConfiguration("--features=parse_headers"); ConfiguredTarget x = scratchConfiguredTarget("x", "x", "cc_library(name = 'x', hdrs = ['x.cc'])"); assertThat(getGeneratingAction(getBinArtifact("_objs/x/x/x.pic.o", x))).isNull(); }
@Test public void testCppModuleMap() throws Exception { AnalysisMock.get() .ccSupport() .setupCrosstool(mockToolsConfig, "feature { name: 'module_maps' }"); useConfiguration(); writeSimpleCcLibrary(); CppModuleMapAction action = getCppModuleMapAction("//module:map"); assertThat(ActionsTestUtil.baseArtifactNames(action.getDependencyArtifacts())) .containsExactly("stl.cppmap", "crosstool.cppmap"); assertEquals(ImmutableSet.of("src module/a.h"), artifactsToStrings(action.getPrivateHeaders())); assertThat(action.getPublicHeaders()).isEmpty(); }
@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 testProcessHeadersInCompileOnlyMode() throws Exception { AnalysisMock.get() .ccSupport() .setupCrosstool(mockToolsConfig, MockCcSupport.HEADER_PROCESSING_FEATURE_CONFIGURATION); useConfiguration("--features=parse_headers", "--process_headers_in_dependencies"); ConfiguredTarget y = scratchConfiguredTarget( "foo", "y", "cc_library(name = 'x', deps = [':y'])", "cc_library(name = 'y', hdrs = ['y.h'])"); assertThat(ActionsTestUtil.baseNamesOf(getOutputGroup(y, OutputGroupProvider.FILES_TO_COMPILE))) .isEqualTo("y.h.processed"); }
@Test public void testDoNotProcessHeadersInDependencies() throws Exception { AnalysisMock.get() .ccSupport() .setupCrosstool(mockToolsConfig, MockCcSupport.HEADER_PROCESSING_FEATURE_CONFIGURATION); useConfiguration("--features=parse_headers"); ConfiguredTarget x = scratchConfiguredTarget( "foo", "x", "cc_library(name = 'x', deps = [':y'])", "cc_library(name = 'y', hdrs = ['y.h'])"); assertThat(ActionsTestUtil.baseNamesOf(getOutputGroup(x, OutputGroupProvider.HIDDEN_TOP_LEVEL))) .isEmpty(); }
@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"); }
@Test public void testBuildHeaderModulesAsPrerequisites() throws Exception { AnalysisMock.get() .ccSupport() .setupCrosstool(mockToolsConfig, MockCcSupport.HEADER_MODULES_FEATURE_CONFIGURATION); useConfiguration(); ConfiguredTarget x = scratchConfiguredTarget( "foo", "x", "package(features = ['header_modules'])", "cc_library(name = 'x', srcs = ['x.cc'], deps = [':y'])", "cc_library(name = 'y', hdrs = ['y.h'])"); assertThat( ActionsTestUtil.baseNamesOf( getOutputGroup(x, OutputGroupProvider.COMPILATION_PREREQUISITES))) .isEqualTo("y.h y.pic.pcm y.cppmap stl.cppmap crosstool.cppmap x.cppmap x.cc"); }
@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(); }
@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"); }