/*
* Copyright 2016-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.shell;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargets;
import com.facebook.buck.rules.AddToRuleKey;
import com.facebook.buck.rules.BinaryBuildRule;
import com.facebook.buck.rules.BuildInfo;
import com.facebook.buck.rules.BuildOutputInitializer;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.CommandTool;
import com.facebook.buck.rules.HasRuntimeDeps;
import com.facebook.buck.rules.InitializableFromDisk;
import com.facebook.buck.rules.NoopBuildRule;
import com.facebook.buck.rules.OnDiskBuildInfo;
import com.facebook.buck.rules.RuleKey;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.Tool;
import com.facebook.buck.rules.args.Arg;
import com.facebook.buck.util.MoreCollectors;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.hash.HashCode;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;
public class DefaultWorkerTool extends NoopBuildRule
implements HasRuntimeDeps, WorkerTool, InitializableFromDisk<DefaultWorkerTool.Data> {
@AddToRuleKey private final ImmutableList<Arg> args;
@AddToRuleKey
@SuppressWarnings("PMD.UnusedPrivateField")
private final ImmutableMap<String, Arg> env;
private final BinaryBuildRule exe;
private final int maxWorkers;
private final boolean isPersistent;
private final BuildOutputInitializer<Data> buildOutputInitializer;
private final Tool tool;
protected DefaultWorkerTool(
BuildRuleParams ruleParams,
BinaryBuildRule exe,
ImmutableList<Arg> args,
ImmutableMap<String, Arg> env,
int maxWorkers,
boolean isPersistent) {
super(ruleParams);
this.exe = exe;
this.args = args;
this.env = env;
this.maxWorkers = maxWorkers;
this.isPersistent = isPersistent;
this.buildOutputInitializer = new BuildOutputInitializer<>(getBuildTarget(), this);
Tool baseTool = this.exe.getExecutableCommand();
CommandTool.Builder builder =
new CommandTool.Builder(baseTool)
.addInputs(
this.getBuildDeps()
.stream()
.map(BuildRule::getSourcePathToOutput)
.collect(MoreCollectors.toImmutableList()));
for (Map.Entry<String, Arg> e : env.entrySet()) {
builder.addEnv(e.getKey(), e.getValue());
}
tool = builder.build();
}
@Override
public Tool getTool() {
return tool;
}
@Override
public String getArgs(SourcePathResolver pathResolver) {
ImmutableList.Builder<String> command = ImmutableList.builder();
for (Arg arg : args) {
arg.appendToCommandLine(command, pathResolver);
}
return Joiner.on(' ').join(command.build());
}
@Override
public Path getTempDir() {
return BuildTargets.getScratchPath(getProjectFilesystem(), getBuildTarget(), "%s__worker");
}
@Override
public int getMaxWorkers() {
return maxWorkers;
}
@Override
public boolean isPersistent() {
return isPersistent;
}
@Override
public Stream<BuildTarget> getRuntimeDeps() {
return getBuildDeps().stream().map(BuildRule::getBuildTarget);
}
@Override
public HashCode getInstanceKey() {
return buildOutputInitializer.getBuildOutput().getRuleKey().getHashCode();
}
@Override
public Data initializeFromDisk(OnDiskBuildInfo onDiskBuildInfo) throws IOException {
Optional<RuleKey> ruleKey = onDiskBuildInfo.getRuleKey(BuildInfo.MetadataKey.RULE_KEY);
if (!ruleKey.isPresent()) {
throw new IllegalStateException(
String.format(
"Should not be initializing %s from disk if the rule key is not written.",
getBuildTarget()));
}
return new Data(ruleKey.get());
}
@Override
public BuildOutputInitializer<Data> getBuildOutputInitializer() {
return buildOutputInitializer;
}
public static class Data {
private final RuleKey ruleKey;
public Data(RuleKey ruleKey) {
this.ruleKey = ruleKey;
}
public RuleKey getRuleKey() {
return ruleKey;
}
}
}