/* * Copyright 2015-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain * a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package com.facebook.buck.cxx; import static org.junit.Assert.assertThat; import com.facebook.buck.model.BuildTarget; import com.facebook.buck.model.BuildTargetFactory; import com.facebook.buck.parser.NoSuchBuildTargetException; import com.facebook.buck.rules.BuildRuleResolver; import com.facebook.buck.rules.DefaultTargetNodeToBuildRuleTransformer; import com.facebook.buck.rules.ExplicitBuildTargetSourcePath; import com.facebook.buck.rules.FakeBuildRuleParamsBuilder; import com.facebook.buck.rules.SourcePath; import com.facebook.buck.rules.SourcePathResolver; import com.facebook.buck.rules.SourcePathRuleFinder; import com.facebook.buck.rules.TargetGraph; import com.facebook.buck.rules.args.Arg; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import java.util.Map; import org.hamcrest.Matchers; import org.junit.Test; public class OmnibusTest { @Test public void includedDeps() throws NoSuchBuildTargetException { NativeLinkable a = new OmnibusNode("//:a"); NativeLinkable b = new OmnibusNode("//:b"); NativeLinkTarget root = new OmnibusRootNode("//:root", ImmutableList.of(a, b)); // Verify the spec. Omnibus.OmnibusSpec spec = Omnibus.buildSpec( CxxPlatformUtils.DEFAULT_PLATFORM, ImmutableList.of(root), ImmutableList.of()); assertThat( spec.getGraph().getNodes(), Matchers.containsInAnyOrder(a.getBuildTarget(), b.getBuildTarget())); assertThat( spec.getBody().keySet(), Matchers.containsInAnyOrder(a.getBuildTarget(), b.getBuildTarget())); assertThat(spec.getRoots().keySet(), Matchers.containsInAnyOrder(root.getBuildTarget())); assertThat(spec.getDeps().keySet(), Matchers.empty()); assertThat(spec.getExcluded().keySet(), Matchers.empty()); // Verify the libs. BuildRuleResolver resolver = new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()); SourcePathRuleFinder ruleFinder = new SourcePathRuleFinder(resolver); SourcePathResolver pathResolver = new SourcePathResolver(ruleFinder); ImmutableMap<String, SourcePath> libs = toSonameMap( Omnibus.getSharedLibraries( new FakeBuildRuleParamsBuilder(BuildTargetFactory.newInstance("//:rule")).build(), resolver, ruleFinder, CxxPlatformUtils.DEFAULT_CONFIG, CxxPlatformUtils.DEFAULT_PLATFORM, ImmutableList.of(), ImmutableList.of(root), ImmutableList.of())); assertThat( libs.keySet(), Matchers.containsInAnyOrder(root.getBuildTarget().toString(), "libomnibus.so")); assertCxxLinkContainsNativeLinkableInput( getCxxLinkRule(ruleFinder, libs.get(root.getBuildTarget().toString())), pathResolver, root.getNativeLinkTargetInput(CxxPlatformUtils.DEFAULT_PLATFORM)); assertCxxLinkContainsNativeLinkableInput( getCxxLinkRule(ruleFinder, libs.get("libomnibus.so")), pathResolver, a.getNativeLinkableInput( CxxPlatformUtils.DEFAULT_PLATFORM, Linker.LinkableDepType.STATIC_PIC), b.getNativeLinkableInput( CxxPlatformUtils.DEFAULT_PLATFORM, Linker.LinkableDepType.STATIC_PIC)); } @Test public void excludedAndIncludedDeps() throws NoSuchBuildTargetException { NativeLinkable a = new OmnibusNode("//:a"); NativeLinkable b = new OmnibusSharedOnlyNode("//:b"); NativeLinkTarget root = new OmnibusRootNode("//:root", ImmutableList.of(a, b)); // Verify the spec. Omnibus.OmnibusSpec spec = Omnibus.buildSpec( CxxPlatformUtils.DEFAULT_PLATFORM, ImmutableList.of(root), ImmutableList.of()); assertThat(spec.getGraph().getNodes(), Matchers.containsInAnyOrder(a.getBuildTarget())); assertThat(spec.getBody().keySet(), Matchers.containsInAnyOrder(a.getBuildTarget())); assertThat(spec.getRoots().keySet(), Matchers.containsInAnyOrder(root.getBuildTarget())); assertThat(spec.getDeps().keySet(), Matchers.containsInAnyOrder(b.getBuildTarget())); assertThat(spec.getExcluded().keySet(), Matchers.containsInAnyOrder(b.getBuildTarget())); // Verify the libs. BuildRuleResolver resolver = new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()); SourcePathRuleFinder ruleFinder = new SourcePathRuleFinder(resolver); SourcePathResolver pathResolver = new SourcePathResolver(ruleFinder); ImmutableMap<String, SourcePath> libs = toSonameMap( Omnibus.getSharedLibraries( new FakeBuildRuleParamsBuilder(BuildTargetFactory.newInstance("//:rule")).build(), resolver, ruleFinder, CxxPlatformUtils.DEFAULT_CONFIG, CxxPlatformUtils.DEFAULT_PLATFORM, ImmutableList.of(), ImmutableList.of(root), ImmutableList.of())); assertThat( libs.keySet(), Matchers.containsInAnyOrder( root.getBuildTarget().toString(), b.getBuildTarget().toString(), "libomnibus.so")); assertCxxLinkContainsNativeLinkableInput( getCxxLinkRule(ruleFinder, libs.get(root.getBuildTarget().toString())), pathResolver, root.getNativeLinkTargetInput(CxxPlatformUtils.DEFAULT_PLATFORM), b.getNativeLinkableInput(CxxPlatformUtils.DEFAULT_PLATFORM, Linker.LinkableDepType.SHARED)); assertThat( libs.get(b.getBuildTarget().toString()), Matchers.not(Matchers.instanceOf(ExplicitBuildTargetSourcePath.class))); assertCxxLinkContainsNativeLinkableInput( getCxxLinkRule(ruleFinder, libs.get("libomnibus.so")), pathResolver, a.getNativeLinkableInput( CxxPlatformUtils.DEFAULT_PLATFORM, Linker.LinkableDepType.STATIC_PIC)); } @Test public void excludedDepExcludesTransitiveDep() throws NoSuchBuildTargetException { NativeLinkable a = new OmnibusNode("//:a"); NativeLinkable b = new OmnibusNode("//:b"); NativeLinkable c = new OmnibusSharedOnlyNode("//:c", ImmutableList.of(b)); NativeLinkTarget root = new OmnibusRootNode("//:root", ImmutableList.of(a, c)); // Verify the spec. Omnibus.OmnibusSpec spec = Omnibus.buildSpec( CxxPlatformUtils.DEFAULT_PLATFORM, ImmutableList.of(root), ImmutableList.of()); assertThat(spec.getGraph().getNodes(), Matchers.containsInAnyOrder(a.getBuildTarget())); assertThat(spec.getBody().keySet(), Matchers.containsInAnyOrder(a.getBuildTarget())); assertThat(spec.getRoots().keySet(), Matchers.containsInAnyOrder(root.getBuildTarget())); assertThat(spec.getDeps().keySet(), Matchers.containsInAnyOrder(c.getBuildTarget())); assertThat( spec.getExcluded().keySet(), Matchers.containsInAnyOrder(b.getBuildTarget(), c.getBuildTarget())); // Verify the libs. BuildRuleResolver resolver = new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()); SourcePathRuleFinder ruleFinder = new SourcePathRuleFinder(resolver); SourcePathResolver pathResolver = new SourcePathResolver(ruleFinder); ImmutableMap<String, SourcePath> libs = toSonameMap( Omnibus.getSharedLibraries( new FakeBuildRuleParamsBuilder(BuildTargetFactory.newInstance("//:rule")).build(), resolver, ruleFinder, CxxPlatformUtils.DEFAULT_CONFIG, CxxPlatformUtils.DEFAULT_PLATFORM, ImmutableList.of(), ImmutableList.of(root), ImmutableList.of())); assertThat( libs.keySet(), Matchers.containsInAnyOrder( root.getBuildTarget().toString(), b.getBuildTarget().toString(), c.getBuildTarget().toString(), "libomnibus.so")); assertCxxLinkContainsNativeLinkableInput( getCxxLinkRule(ruleFinder, libs.get(root.getBuildTarget().toString())), pathResolver, root.getNativeLinkTargetInput(CxxPlatformUtils.DEFAULT_PLATFORM), c.getNativeLinkableInput(CxxPlatformUtils.DEFAULT_PLATFORM, Linker.LinkableDepType.SHARED)); assertThat( libs.get(b.getBuildTarget().toString()), Matchers.not(Matchers.instanceOf(ExplicitBuildTargetSourcePath.class))); assertThat( libs.get(c.getBuildTarget().toString()), Matchers.not(Matchers.instanceOf(ExplicitBuildTargetSourcePath.class))); assertCxxLinkContainsNativeLinkableInput( getCxxLinkRule(ruleFinder, libs.get("libomnibus.so")), pathResolver, a.getNativeLinkableInput( CxxPlatformUtils.DEFAULT_PLATFORM, Linker.LinkableDepType.STATIC_PIC)); } @Test public void depOfExcludedRoot() throws NoSuchBuildTargetException { NativeLinkable a = new OmnibusNode("//:a"); NativeLinkTarget root = new OmnibusRootNode("//:root", ImmutableList.of(a)); NativeLinkable b = new OmnibusNode("//:b"); NativeLinkable excludedRoot = new OmnibusNode("//:excluded_root", ImmutableList.of(b)); // Verify the spec. Omnibus.OmnibusSpec spec = Omnibus.buildSpec( CxxPlatformUtils.DEFAULT_PLATFORM, ImmutableList.of(root), ImmutableList.of(excludedRoot)); assertThat(spec.getGraph().getNodes(), Matchers.containsInAnyOrder(a.getBuildTarget())); assertThat(spec.getBody().keySet(), Matchers.containsInAnyOrder(a.getBuildTarget())); assertThat(spec.getRoots().keySet(), Matchers.containsInAnyOrder(root.getBuildTarget())); assertThat(spec.getDeps().keySet(), Matchers.empty()); assertThat( spec.getExcluded().keySet(), Matchers.containsInAnyOrder(excludedRoot.getBuildTarget(), b.getBuildTarget())); // Verify the libs. BuildRuleResolver resolver = new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()); SourcePathRuleFinder ruleFinder = new SourcePathRuleFinder(resolver); SourcePathResolver pathResolver = new SourcePathResolver(ruleFinder); ImmutableMap<String, SourcePath> libs = toSonameMap( Omnibus.getSharedLibraries( new FakeBuildRuleParamsBuilder(BuildTargetFactory.newInstance("//:rule")).build(), resolver, ruleFinder, CxxPlatformUtils.DEFAULT_CONFIG, CxxPlatformUtils.DEFAULT_PLATFORM, ImmutableList.of(), ImmutableList.of(root), ImmutableList.of(excludedRoot))); assertThat( libs.keySet(), Matchers.containsInAnyOrder( root.getBuildTarget().toString(), excludedRoot.getBuildTarget().toString(), b.getBuildTarget().toString(), "libomnibus.so")); assertCxxLinkContainsNativeLinkableInput( getCxxLinkRule(ruleFinder, libs.get(root.getBuildTarget().toString())), pathResolver, root.getNativeLinkTargetInput(CxxPlatformUtils.DEFAULT_PLATFORM)); assertThat( libs.get(excludedRoot.getBuildTarget().toString()), Matchers.not(Matchers.instanceOf(ExplicitBuildTargetSourcePath.class))); assertThat( libs.get(b.getBuildTarget().toString()), Matchers.not(Matchers.instanceOf(ExplicitBuildTargetSourcePath.class))); assertCxxLinkContainsNativeLinkableInput( getCxxLinkRule(ruleFinder, libs.get("libomnibus.so")), pathResolver, a.getNativeLinkableInput( CxxPlatformUtils.DEFAULT_PLATFORM, Linker.LinkableDepType.STATIC_PIC)); } @Test public void commondDepOfIncludedAndExcludedRoots() throws NoSuchBuildTargetException { NativeLinkable a = new OmnibusNode("//:a"); NativeLinkTarget root = new OmnibusRootNode("//:root", ImmutableList.of(a)); NativeLinkable excludedRoot = new OmnibusNode("//:excluded_root", ImmutableList.of(a)); // Verify the spec. Omnibus.OmnibusSpec spec = Omnibus.buildSpec( CxxPlatformUtils.DEFAULT_PLATFORM, ImmutableList.of(root), ImmutableList.of(excludedRoot)); assertThat(spec.getGraph().getNodes(), Matchers.empty()); assertThat(spec.getBody().keySet(), Matchers.empty()); assertThat(spec.getRoots().keySet(), Matchers.containsInAnyOrder(root.getBuildTarget())); assertThat(spec.getDeps().keySet(), Matchers.containsInAnyOrder(a.getBuildTarget())); assertThat( spec.getExcluded().keySet(), Matchers.containsInAnyOrder(excludedRoot.getBuildTarget(), a.getBuildTarget())); // Verify the libs. BuildRuleResolver resolver = new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()); SourcePathRuleFinder ruleFinder = new SourcePathRuleFinder(resolver); SourcePathResolver pathResolver = new SourcePathResolver(ruleFinder); ImmutableMap<String, SourcePath> libs = toSonameMap( Omnibus.getSharedLibraries( new FakeBuildRuleParamsBuilder(BuildTargetFactory.newInstance("//:rule")).build(), resolver, ruleFinder, CxxPlatformUtils.DEFAULT_CONFIG, CxxPlatformUtils.DEFAULT_PLATFORM, ImmutableList.of(), ImmutableList.of(root), ImmutableList.of(excludedRoot))); assertThat( libs.keySet(), Matchers.containsInAnyOrder( root.getBuildTarget().toString(), excludedRoot.getBuildTarget().toString(), a.getBuildTarget().toString())); assertCxxLinkContainsNativeLinkableInput( getCxxLinkRule(ruleFinder, libs.get(root.getBuildTarget().toString())), pathResolver, root.getNativeLinkTargetInput(CxxPlatformUtils.DEFAULT_PLATFORM)); assertThat( libs.get(excludedRoot.getBuildTarget().toString()), Matchers.not(Matchers.instanceOf(ExplicitBuildTargetSourcePath.class))); assertThat( libs.get(a.getBuildTarget().toString()), Matchers.not(Matchers.instanceOf(ExplicitBuildTargetSourcePath.class))); } @Test public void unusedStaticDepsAreNotIncludedInBody() throws NoSuchBuildTargetException { NativeLinkable a = new OmnibusNode( "//:a", ImmutableList.of(), ImmutableList.of(), NativeLinkable.Linkage.STATIC); NativeLinkable b = new OmnibusNode("//:b"); NativeLinkTarget root = new OmnibusRootNode("//:root", ImmutableList.of(a, b)); // Verify the spec. Omnibus.OmnibusSpec spec = Omnibus.buildSpec( CxxPlatformUtils.DEFAULT_PLATFORM, ImmutableList.of(root), ImmutableList.of()); assertThat(spec.getGraph().getNodes(), Matchers.containsInAnyOrder(b.getBuildTarget())); assertThat(spec.getBody().keySet(), Matchers.containsInAnyOrder(b.getBuildTarget())); assertThat(spec.getRoots().keySet(), Matchers.containsInAnyOrder(root.getBuildTarget())); assertThat(spec.getDeps().keySet(), Matchers.empty()); assertThat(spec.getExcluded().keySet(), Matchers.empty()); // Verify the libs. BuildRuleResolver resolver = new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()); SourcePathRuleFinder ruleFinder = new SourcePathRuleFinder(resolver); SourcePathResolver pathResolver = new SourcePathResolver(ruleFinder); ImmutableMap<String, SourcePath> libs = toSonameMap( Omnibus.getSharedLibraries( new FakeBuildRuleParamsBuilder(BuildTargetFactory.newInstance("//:rule")).build(), resolver, ruleFinder, CxxPlatformUtils.DEFAULT_CONFIG, CxxPlatformUtils.DEFAULT_PLATFORM, ImmutableList.of(), ImmutableList.of(root), ImmutableList.of())); assertThat( libs.keySet(), Matchers.containsInAnyOrder(root.getBuildTarget().toString(), "libomnibus.so")); assertCxxLinkContainsNativeLinkableInput( getCxxLinkRule(ruleFinder, libs.get(root.getBuildTarget().toString())), pathResolver, root.getNativeLinkTargetInput(CxxPlatformUtils.DEFAULT_PLATFORM), a.getNativeLinkableInput( CxxPlatformUtils.DEFAULT_PLATFORM, Linker.LinkableDepType.STATIC_PIC)); assertCxxLinkContainsNativeLinkableInput( getCxxLinkRule(ruleFinder, libs.get("libomnibus.so")), pathResolver, b.getNativeLinkableInput( CxxPlatformUtils.DEFAULT_PLATFORM, Linker.LinkableDepType.STATIC_PIC)); } private CxxLink getCxxLinkRule(SourcePathRuleFinder ruleFinder, SourcePath path) { return ((CxxLink) ruleFinder.getRuleOrThrow((ExplicitBuildTargetSourcePath) path)); } private void assertCxxLinkContainsNativeLinkableInput( CxxLink link, SourcePathResolver pathResolver, NativeLinkableInput... inputs) { for (NativeLinkableInput input : inputs) { assertThat( Arg.stringify(link.getArgs(), pathResolver), Matchers.hasItems(Arg.stringify(input.getArgs(), pathResolver).toArray(new String[1]))); } } private ImmutableMap<String, SourcePath> toSonameMap(OmnibusLibraries libraries) { ImmutableMap.Builder<String, SourcePath> map = ImmutableMap.builder(); for (Map.Entry<BuildTarget, OmnibusRoot> root : libraries.getRoots().entrySet()) { map.put(root.getKey().toString(), root.getValue().getPath()); } for (OmnibusLibrary library : libraries.getLibraries()) { map.put(library.getSoname(), library.getPath()); } return map.build(); } }