@Override public ResolvedTargets<Void> getExplicitTarget(String targetName) throws TargetParsingException, InterruptedException { Label label = TargetPatternResolverUtil.label(targetName); try { Target target = packageProvider.getTarget(env.getListener(), label); SkyKey key = TransitiveTraversalValue.key(target.getLabel()); SkyValue token = env.getValueOrThrow(key, NoSuchPackageException.class, NoSuchTargetException.class); if (token == null) { throw new MissingDepException(); } return ResolvedTargets.empty(); } catch (NoSuchThingException e) { throw new TargetParsingException(e.getMessage(), e); } }
@Override @Nullable public BuildConfiguration createConfigurations( ConfigurationFactory configurationFactory, Cache<String, BuildConfiguration> cache, PackageProviderForConfigurations packageProvider, BuildOptions buildOptions, EventHandler eventHandler, boolean performSanityCheck) throws InvalidConfigurationException { // Target configuration BuildConfiguration targetConfiguration = configurationFactory.getConfiguration(packageProvider, buildOptions, false, cache); if (targetConfiguration == null) { return null; } BuildConfiguration dataConfiguration = targetConfiguration; // Host configuration // Note that this passes in the dataConfiguration, not the target // configuration. This is intentional. BuildConfiguration hostConfiguration = getHostConfigurationFromRequest( configurationFactory, packageProvider, dataConfiguration, buildOptions, cache); if (hostConfiguration == null) { return null; } ListMultimap<SplitTransition<?>, BuildConfiguration> splitTransitionsTable = ArrayListMultimap.create(); for (SplitTransition<BuildOptions> transition : buildOptions.getPotentialSplitTransitions()) { List<BuildOptions> splitOptionsList = transition.split(buildOptions); // While it'd be clearer to condition the below on "if (!splitOptionsList.empty())", // IosExtension.ExtensionSplitArchTransition defaults to a single-value split. If we failed // that case then no builds would work, whether or not they're iOS builds (since iOS // configurations are unconditionally loaded). Once we have dynamic configuraiton support // for split transitions, this will all go away. if (splitOptionsList.size() > 1 && targetConfiguration.useDynamicConfigurations()) { throw new InvalidConfigurationException( "dynamic configurations don't yet support split transitions"); } for (BuildOptions splitOptions : splitOptionsList) { BuildConfiguration splitConfig = configurationFactory.getConfiguration(packageProvider, splitOptions, false, cache); splitTransitionsTable.put(transition, splitConfig); } } if (packageProvider.valuesMissing()) { return null; } // Sanity check that the implicit labels are all in the transitive closure of explicit ones. // This also registers all targets in the cache entry and validates them on subsequent requests. Set<Label> reachableLabels = new HashSet<>(); if (performSanityCheck) { // We allow the package provider to be null for testing. for (Map.Entry<String, Label> entry : buildOptions.getAllLabels().entries()) { Label label = entry.getValue(); try { collectTransitiveClosure(packageProvider, reachableLabels, label); } catch (NoSuchThingException e) { eventHandler.handle(Event.error(e.getMessage())); throw new InvalidConfigurationException( String.format("Failed to load required %s target: '%s'", entry.getKey(), label)); } } if (packageProvider.valuesMissing()) { return null; } sanityCheckImplicitLabels(reachableLabels, targetConfiguration); sanityCheckImplicitLabels(reachableLabels, hostConfiguration); } BuildConfiguration result = setupTransitions( targetConfiguration, dataConfiguration, hostConfiguration, splitTransitionsTable); result.reportInvalidOptions(eventHandler); return result; }