@Override public void run() { while (shouldWaitForWork()) { try (BuildTargetProcessingScope processingScope = startProcessingBuildTarget()) { // If we've already parsed this in another thread, we can skip doing any work. if (permState.hasCachedTargetNodeForBuildTarget(processingScope.getBuildTarget())) { continue; } TargetNode<?> node; try (SimplePerfEvent.Scope scope = Parser.getTargetNodeEventScope(eventBus, processingScope.getBuildTarget())) { try { node = getTargetNode(processingScope.getBuildTarget()); } catch (BuildFileParseException | BuildTargetException | IOException e) { // It's okay to not raise this further up because in `Parser` we build the target // graph and while doing so will hit the same error (the parsing will have been // cached). abortDoingMoreWork(); return; } } processingScope.addDepsToProcess( FluentIterable.from(node.getDeps()) .filter(permState.getHasCachedTargetNodeForBuildTargetPredicate()) .toSet()); } catch (TimeoutException e) { // We timed out waiting to process something on the queue. This could mean we are done, // so run through the while statement again. continue; } catch (InterruptedException e) { abortDoingMoreWork(); return; } } }
@Test public void shouldBeAbleToConstructACxxLibraryFromThrift() throws Exception { ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(this, "cxx", tmp); workspace.setUp(); BuckEventBus eventBus = BuckEventBusFactory.newInstance(); ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath()); Path compiler = new ExecutableFinder() .getExecutable(Paths.get("echo"), ImmutableMap.copyOf(System.getenv())); BuckConfig config = FakeBuckConfig.builder() .setFilesystem(filesystem) .setSections( "[thrift]", "compiler = " + compiler, "compiler2 = " + compiler, "cpp_library = //thrift:fake", "cpp_reflection_library = //thrift:fake") .build(); TypeCoercerFactory typeCoercerFactory = new DefaultTypeCoercerFactory(); Parser parser = new Parser( new ParserConfig(config), typeCoercerFactory, new ConstructorArgMarshaller(typeCoercerFactory)); Cell cell = Cell.createCell( filesystem, new TestConsole(), Watchman.NULL_WATCHMAN, config, new KnownBuildRuleTypesFactory( new ProcessExecutor(new TestConsole()), new FakeAndroidDirectoryResolver(), Optional.<Path>absent()), new FakeAndroidDirectoryResolver(), new DefaultClock()); BuildTarget target = BuildTargetFactory.newInstance(filesystem, "//thrift:exe"); TargetGraph targetGraph = parser.buildTargetGraph( eventBus, cell, false, Executors.newSingleThreadExecutor(), ImmutableSet.of(target)); TargetNodeToBuildRuleTransformer transformer = new BuildTargetNodeToBuildRuleTransformer(); // There was a case where the cxx library being generated wouldn't put the header into the tree // with the right flavour. This catches this case without us needing to stick a working thrift // compiler into buck's own source. Pair<ActionGraph, BuildRuleResolver> actionGraphAndResolver = new TargetGraphToActionGraph(eventBus, transformer).apply(targetGraph); // This is to cover the case where we weren't passing flavors around correctly, which ended // making the binary depend 'placeholder' BuildRules instead of real ones. This is the // regression test for that case. BuildRuleResolver ruleResolver = actionGraphAndResolver.getSecond(); BuildTarget binaryFlavor = target.withFlavors(ImmutableFlavor.of("binary")); ImmutableSortedSet<BuildRule> deps = ruleResolver.getRule(binaryFlavor).getDeps(); assertThat( FluentIterable.from(deps) .anyMatch( new Predicate<BuildRule>() { @Override public boolean apply(BuildRule input) { return input instanceof NoopBuildRule; } }), Matchers.is(false)); }