use of com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction in project bazel by bazelbuild.
the class CppLinkActionBuilder method build.
/** Builds the Action as configured and returns it. */
public CppLinkAction build() throws InterruptedException {
// Executable links do not have library identifiers.
boolean hasIdentifier = (libraryIdentifier != null);
boolean isExecutable = linkType.isExecutable();
Preconditions.checkState(hasIdentifier != isExecutable);
if (interfaceOutput != null && (fake || linkType != LinkTargetType.DYNAMIC_LIBRARY)) {
throw new RuntimeException("Interface output can only be used " + "with non-fake DYNAMIC_LIBRARY targets");
}
final ImmutableList<Artifact> buildInfoHeaderArtifacts = !linkstamps.isEmpty() ? analysisEnvironment.getBuildInfo(ruleContext, CppBuildInfo.KEY, configuration) : ImmutableList.<Artifact>of();
boolean needWholeArchive = wholeArchive || needWholeArchive(linkStaticness, linkType, linkopts, isNativeDeps, cppConfiguration);
NestedSet<LibraryToLink> uniqueLibraries = libraries.build();
final Iterable<Artifact> objectArtifacts = LinkerInputs.toLibraryArtifacts(objectFiles);
final Iterable<LinkerInput> linkerInputs = IterablesChain.<LinkerInput>builder().add(ImmutableList.copyOf(objectFiles)).add(ImmutableIterable.from(Link.mergeInputsCmdLine(uniqueLibraries, needWholeArchive, cppConfiguration.archiveType()))).build();
// ruleContext can only be null during testing. This is kind of ugly.
final ImmutableSet<String> features = (ruleContext == null) ? ImmutableSet.<String>of() : ruleContext.getFeatures();
// instantiated without a feature configuration.
if (featureConfiguration == null) {
if (toolchain != null) {
featureConfiguration = CcCommon.configureFeatures(ruleContext, toolchain, CcLibraryHelper.SourceCategory.CC);
} else {
featureConfiguration = CcCommon.configureFeatures(ruleContext, toolchain);
}
}
final LibraryToLink outputLibrary = linkType.isExecutable() ? null : LinkerInputs.newInputLibrary(output, linkType.getLinkerOutput(), libraryIdentifier, objectArtifacts, this.ltoBitcodeFiles);
final LibraryToLink interfaceOutputLibrary = (interfaceOutput == null) ? null : LinkerInputs.newInputLibrary(interfaceOutput, ArtifactCategory.DYNAMIC_LIBRARY, libraryIdentifier, objectArtifacts, this.ltoBitcodeFiles);
final ImmutableMap<Artifact, Artifact> linkstampMap = mapLinkstampsToOutputs(linkstamps, ruleContext, configuration, output, linkArtifactFactory);
PathFragment ltoOutputRootPrefix = null;
if (isLTOIndexing && allLTOArtifacts == null) {
ltoOutputRootPrefix = FileSystemUtils.appendExtension(output.getRootRelativePath(), ".lto");
allLTOArtifacts = createLTOArtifacts(ltoOutputRootPrefix, uniqueLibraries);
}
PathFragment linkerParamFileRootPath = null;
@Nullable Artifact thinltoParamFile = null;
if (allLTOArtifacts != null) {
// Create artifact for the file that the LTO indexing step will emit
// object file names into for any that were included in the link as
// determined by the linker's symbol resolution. It will be used to
// provide the inputs for the subsequent final native object link.
// Note that the paths emitted into this file will have their prefixes
// replaced with the final output directory, so they will be the paths
// of the native object files not the input bitcode files.
linkerParamFileRootPath = ParameterFile.derivePath(output.getRootRelativePath(), "lto-final");
thinltoParamFile = linkArtifactFactory.create(ruleContext, configuration, linkerParamFileRootPath);
}
final ImmutableList<Artifact> actionOutputs;
if (isLTOIndexing) {
ImmutableList.Builder<Artifact> builder = ImmutableList.builder();
for (LTOBackendArtifacts ltoA : allLTOArtifacts) {
ltoA.addIndexingOutputs(builder);
}
if (thinltoParamFile != null) {
builder.add(thinltoParamFile);
}
actionOutputs = builder.build();
} else {
actionOutputs = constructOutputs(output, linkstampMap.values(), interfaceOutputLibrary == null ? null : interfaceOutputLibrary.getArtifact(), symbolCounts);
}
ImmutableList<LinkerInput> runtimeLinkerInputs = ImmutableList.copyOf(LinkerInputs.simpleLinkerInputs(runtimeInputs, runtimeType));
PathFragment paramRootPath = ParameterFile.derivePath(output.getRootRelativePath(), (isLTOIndexing) ? "lto-index" : "2");
@Nullable final Artifact paramFile = canSplitCommandLine() ? linkArtifactFactory.create(ruleContext, configuration, paramRootPath) : null;
// Add build variables necessary to template link args into the crosstool.
Variables.Builder buildVariablesBuilder = new Variables.Builder();
CppLinkVariablesExtension variablesExtension = isLTOIndexing ? new CppLinkVariablesExtension(configuration, ImmutableMap.<Artifact, Artifact>of(), needWholeArchive, linkerInputs, runtimeLinkerInputs, null, paramFile, thinltoParamFile, ltoOutputRootPrefix, null, null) : new CppLinkVariablesExtension(configuration, linkstampMap, needWholeArchive, linkerInputs, runtimeLinkerInputs, output, paramFile, thinltoParamFile, PathFragment.EMPTY_FRAGMENT, toolchain.getInterfaceSoBuilder(), interfaceOutput);
variablesExtension.addVariables(buildVariablesBuilder);
for (VariablesExtension extraVariablesExtension : variablesExtensions) {
extraVariablesExtension.addVariables(buildVariablesBuilder);
}
Variables buildVariables = buildVariablesBuilder.build();
Preconditions.checkArgument(linkType != LinkTargetType.INTERFACE_DYNAMIC_LIBRARY, "you can't link an interface dynamic library directly");
if (linkType != LinkTargetType.DYNAMIC_LIBRARY) {
Preconditions.checkArgument(interfaceOutput == null, "interface output may only be non-null for dynamic library links");
}
if (linkType.staticness() == Staticness.STATIC) {
// solib dir must be null for static links
runtimeSolibDir = null;
Preconditions.checkArgument(linkStaticness == LinkStaticness.FULLY_STATIC, "static library link must be static");
Preconditions.checkArgument(symbolCounts == null, "the symbol counts output must be null for static links");
Preconditions.checkArgument(!isNativeDeps, "the native deps flag must be false for static links");
Preconditions.checkArgument(!needWholeArchive, "the need whole archive flag must be false for static links");
}
LinkCommandLine.Builder linkCommandLineBuilder = new LinkCommandLine.Builder(configuration, getOwner(), ruleContext).setLinkerInputs(linkerInputs).setRuntimeInputs(runtimeLinkerInputs).setLinkTargetType(linkType).setLinkStaticness(linkStaticness).setFeatures(features).setRuntimeSolibDir(linkType.staticness() == Staticness.STATIC ? null : runtimeSolibDir).setNativeDeps(isNativeDeps).setUseTestOnlyFlags(useTestOnlyFlags).setParamFile(paramFile).setToolchain(toolchain).setFdoSupport(fdoSupport.getFdoSupport()).setBuildVariables(buildVariables).setToolPath(getToolPath()).setFeatureConfiguration(featureConfiguration);
if (!isLTOIndexing) {
linkCommandLineBuilder.setOutput(output).setBuildInfoHeaderArtifacts(buildInfoHeaderArtifacts).setLinkstamps(linkstampMap).setLinkopts(ImmutableList.copyOf(linkopts)).addLinkstampCompileOptions(linkstampOptions);
} else {
List<String> opts = new ArrayList<>(linkopts);
opts.addAll(featureConfiguration.getCommandLine("lto-indexing", buildVariables));
opts.addAll(cppConfiguration.getLTOIndexOptions());
linkCommandLineBuilder.setLinkopts(ImmutableList.copyOf(opts));
}
LinkCommandLine linkCommandLine = linkCommandLineBuilder.build();
// Compute the set of inputs - we only need stable order here.
NestedSetBuilder<Artifact> dependencyInputsBuilder = NestedSetBuilder.stableOrder();
dependencyInputsBuilder.addTransitive(crosstoolInputs);
dependencyInputsBuilder.add(toolchain.getLinkDynamicLibraryTool());
dependencyInputsBuilder.addTransitive(linkActionInputs.build());
if (runtimeMiddleman != null) {
dependencyInputsBuilder.add(runtimeMiddleman);
}
if (!isLTOIndexing) {
dependencyInputsBuilder.addAll(buildInfoHeaderArtifacts);
dependencyInputsBuilder.addAll(linkstamps);
dependencyInputsBuilder.addTransitive(compilationInputs.build());
}
Iterable<Artifact> expandedInputs = LinkerInputs.toLibraryArtifacts(Link.mergeInputsDependencies(uniqueLibraries, needWholeArchive, cppConfiguration.archiveType()));
Iterable<Artifact> expandedNonLibraryInputs = LinkerInputs.toLibraryArtifacts(objectFiles);
if (!isLTOIndexing && allLTOArtifacts != null) {
// We are doing LTO, and this is the real link, so substitute
// the LTO bitcode files with the real object files they were translated into.
Map<Artifact, Artifact> ltoMapping = new HashMap<>();
for (LTOBackendArtifacts a : allLTOArtifacts) {
ltoMapping.put(a.getBitcodeFile(), a.getObjectFile());
}
// Handle libraries.
List<Artifact> renamedInputs = new ArrayList<>();
for (Artifact a : expandedInputs) {
Artifact renamed = ltoMapping.get(a);
renamedInputs.add(renamed == null ? a : renamed);
}
expandedInputs = renamedInputs;
// Handle non-libraries.
List<Artifact> renamedNonLibraryInputs = new ArrayList<>();
for (Artifact a : expandedNonLibraryInputs) {
Artifact renamed = ltoMapping.get(a);
renamedNonLibraryInputs.add(renamed == null ? a : renamed);
}
expandedNonLibraryInputs = renamedNonLibraryInputs;
} else if (isLTOIndexing && allLTOArtifacts != null) {
for (LTOBackendArtifacts a : allLTOArtifacts) {
List<String> argv = new ArrayList<>();
argv.addAll(cppConfiguration.getLinkOptions());
argv.addAll(cppConfiguration.getCompilerOptions(features));
a.setCommandLine(argv);
a.scheduleLTOBackendAction(ruleContext, featureConfiguration, toolchain, fdoSupport, usePicForLTOBackendActions, useFissionForLTOBackendActions);
}
}
// getPrimaryInput returns the first element, and that is a public interface - therefore the
// order here is important.
IterablesChain.Builder<Artifact> inputsBuilder = IterablesChain.<Artifact>builder().add(ImmutableList.copyOf(expandedNonLibraryInputs)).add(ImmutableList.copyOf(nonCodeInputs)).add(dependencyInputsBuilder.build()).add(ImmutableIterable.from(expandedInputs));
if (thinltoParamFile != null && !isLTOIndexing) {
inputsBuilder.add(ImmutableList.of(thinltoParamFile));
}
if (linkCommandLine.getParamFile() != null) {
inputsBuilder.add(ImmutableList.of(linkCommandLine.getParamFile()));
Action parameterFileWriteAction = new ParameterFileWriteAction(getOwner(), paramFile, linkCommandLine.paramCmdLine(), ParameterFile.ParameterFileType.UNQUOTED, ISO_8859_1);
analysisEnvironment.registerAction(parameterFileWriteAction);
}
ImmutableMap<String, String> toolchainEnv = featureConfiguration.getEnvironmentVariables(getActionName(), buildVariables);
// If the crosstool uses action_configs to configure cc compilation, collect execution info
// from there, otherwise, use no execution info.
// TODO(b/27903698): Assert that the crosstool has an action_config for this action.
ImmutableSet.Builder<String> executionRequirements = ImmutableSet.<String>builder();
if (featureConfiguration.actionIsConfigured(getActionName())) {
executionRequirements.addAll(featureConfiguration.getToolForAction(getActionName()).getExecutionRequirements());
}
return new CppLinkAction(getOwner(), mnemonic, inputsBuilder.deduplicate().build(), actionOutputs, cppConfiguration, outputLibrary, output, interfaceOutputLibrary, fake, isLTOIndexing, allLTOArtifacts, linkCommandLine, configuration.getVariableShellEnvironment(), configuration.getLocalShellEnvironment(), toolchainEnv, executionRequirements.build());
}
use of com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction in project bazel by bazelbuild.
the class DexArchiveAspect method createDesugarAction.
private static Artifact createDesugarAction(RuleContext ruleContext, String desugarPrereqName, Artifact jar, ImmutableList<Artifact> bootclasspath, NestedSet<Artifact> classpath, Artifact result) {
CustomCommandLine args = new CustomCommandLine.Builder().addExecPath("--input", jar).addExecPath("--output", result).addBeforeEachExecPath("--classpath_entry", classpath).addBeforeEachExecPath("--bootclasspath_entry", bootclasspath).build();
// Just use params file, since classpaths can get long
Artifact paramFile = ruleContext.getDerivedArtifact(ParameterFile.derivePath(result.getRootRelativePath()), result.getRoot());
ruleContext.registerAction(new ParameterFileWriteAction(ruleContext.getActionOwner(), paramFile, args, ParameterFile.ParameterFileType.UNQUOTED, ISO_8859_1));
ruleContext.registerAction(new SpawnAction.Builder().setExecutable(ruleContext.getExecutablePrerequisite(desugarPrereqName, Mode.HOST)).addArgument("@" + paramFile.getExecPathString()).addInput(jar).addInput(paramFile).addInputs(bootclasspath).addTransitiveInputs(classpath).addOutput(result).setMnemonic("Desugar").setProgressMessage("Desugaring " + jar.prettyPrint() + " for Android").build(ruleContext));
return result;
}
use of com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction in project bazel by bazelbuild.
the class J2ObjcAspect method createJ2ObjcTranspilationAction.
private static J2ObjcMappingFileProvider createJ2ObjcTranspilationAction(RuleContext ruleContext, Iterable<Artifact> sources, Iterable<Artifact> sourceJars, J2ObjcMappingFileProvider depJ2ObjcMappingFileProvider, JavaCompilationArgsProvider compArgsProvider, J2ObjcSource j2ObjcSource) {
CustomCommandLine.Builder argBuilder = CustomCommandLine.builder();
PathFragment javaExecutable = ruleContext.getFragment(Jvm.class, HOST).getJavaExecutable();
argBuilder.add("--java").add(javaExecutable.getPathString());
Artifact j2ObjcDeployJar = ruleContext.getPrerequisiteArtifact("$j2objc", Mode.HOST);
argBuilder.addExecPath("--j2objc", j2ObjcDeployJar);
argBuilder.add("--main_class").add("com.google.devtools.j2objc.J2ObjC");
argBuilder.add("--objc_file_path").addPath(j2ObjcSource.getObjcFilePath());
Artifact outputDependencyMappingFile = j2ObjcOutputDependencyMappingFile(ruleContext);
argBuilder.addExecPath("--output_dependency_mapping_file", outputDependencyMappingFile);
ImmutableList.Builder<Artifact> sourceJarOutputFiles = ImmutableList.builder();
if (!Iterables.isEmpty(sourceJars)) {
sourceJarOutputFiles.addAll(sourceJarOutputs(ruleContext));
argBuilder.addJoinExecPaths("--src_jars", ",", sourceJars);
argBuilder.add(sourceJarFlags(ruleContext));
}
Iterable<String> translationFlags = ruleContext.getFragment(J2ObjcConfiguration.class).getTranslationFlags();
argBuilder.add(translationFlags);
NestedSet<Artifact> depsHeaderMappingFiles = depJ2ObjcMappingFileProvider.getHeaderMappingFiles();
if (!depsHeaderMappingFiles.isEmpty()) {
argBuilder.addJoinExecPaths("--header-mapping", ",", depsHeaderMappingFiles);
}
Artifact outputHeaderMappingFile = j2ObjcOutputHeaderMappingFile(ruleContext);
argBuilder.addExecPath("--output-header-mapping", outputHeaderMappingFile);
NestedSet<Artifact> depsClassMappingFiles = depJ2ObjcMappingFileProvider.getClassMappingFiles();
if (!depsClassMappingFiles.isEmpty()) {
argBuilder.addJoinExecPaths("--mapping", ",", depsClassMappingFiles);
}
Artifact archiveSourceMappingFile = j2ObjcOutputArchiveSourceMappingFile(ruleContext);
argBuilder.addExecPath("--output_archive_source_mapping_file", archiveSourceMappingFile);
Artifact compiledLibrary = ObjcRuleClasses.j2objcIntermediateArtifacts(ruleContext).archive();
argBuilder.addExecPath("--compiled_archive_file_path", compiledLibrary);
Artifact bootclasspathJar = ruleContext.getPrerequisiteArtifact("$jre_emul_jar", Mode.HOST);
argBuilder.add("-Xbootclasspath:" + bootclasspathJar.getExecPathString());
argBuilder.add("-d").addPath(j2ObjcSource.getObjcFilePath());
NestedSet<Artifact> compileTimeJars = compArgsProvider.getRecursiveJavaCompilationArgs().getCompileTimeJars();
if (!compileTimeJars.isEmpty()) {
argBuilder.addJoinExecPaths("-classpath", ":", compileTimeJars);
}
argBuilder.addExecPaths(sources);
Artifact paramFile = j2ObjcOutputParamFile(ruleContext);
ruleContext.registerAction(new ParameterFileWriteAction(ruleContext.getActionOwner(), paramFile, argBuilder.build(), ParameterFile.ParameterFileType.UNQUOTED, ISO_8859_1));
SpawnAction.Builder builder = new SpawnAction.Builder().setMnemonic("TranspilingJ2objc").setExecutable(ruleContext.getPrerequisiteArtifact("$j2objc_wrapper", Mode.HOST)).addInput(ruleContext.getPrerequisiteArtifact("$j2objc_wrapper", Mode.HOST)).addInput(j2ObjcDeployJar).addInput(bootclasspathJar).addInputs(sources).addInputs(sourceJars).addTransitiveInputs(compileTimeJars).addTransitiveInputs(JavaHelper.getHostJavabaseInputs(ruleContext)).addTransitiveInputs(depsHeaderMappingFiles).addTransitiveInputs(depsClassMappingFiles).addInput(paramFile).setCommandLine(CustomCommandLine.builder().addPaths("@%s", paramFile.getExecPath()).build()).addOutputs(j2ObjcSource.getObjcSrcs()).addOutputs(j2ObjcSource.getObjcHdrs()).addOutput(outputHeaderMappingFile).addOutput(outputDependencyMappingFile).addOutput(archiveSourceMappingFile);
ruleContext.registerAction(builder.build(ruleContext));
return new J2ObjcMappingFileProvider(NestedSetBuilder.<Artifact>stableOrder().add(outputHeaderMappingFile).build(), NestedSetBuilder.<Artifact>stableOrder().build(), NestedSetBuilder.<Artifact>stableOrder().add(outputDependencyMappingFile).build(), NestedSetBuilder.<Artifact>stableOrder().add(archiveSourceMappingFile).build());
}
use of com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction in project bazel by bazelbuild.
the class CompilationSupport method registerJ2ObjcDeadCodeRemovalActions.
/**
* Registers actions to perform J2Objc dead code removal.
*/
protected void registerJ2ObjcDeadCodeRemovalActions(ObjcProvider objcProvider, J2ObjcMappingFileProvider j2ObjcMappingFileProvider, J2ObjcEntryClassProvider j2ObjcEntryClassProvider) {
NestedSet<String> entryClasses = j2ObjcEntryClassProvider.getEntryClasses();
Artifact pruner = ruleContext.getPrerequisiteArtifact("$j2objc_dead_code_pruner", Mode.HOST);
NestedSet<Artifact> j2ObjcDependencyMappingFiles = j2ObjcMappingFileProvider.getDependencyMappingFiles();
NestedSet<Artifact> j2ObjcHeaderMappingFiles = j2ObjcMappingFileProvider.getHeaderMappingFiles();
NestedSet<Artifact> j2ObjcArchiveSourceMappingFiles = j2ObjcMappingFileProvider.getArchiveSourceMappingFiles();
for (Artifact j2objcArchive : objcProvider.get(ObjcProvider.J2OBJC_LIBRARY)) {
PathFragment paramFilePath = FileSystemUtils.replaceExtension(j2objcArchive.getOwner().toPathFragment(), ".param.j2objc");
Artifact paramFile = ruleContext.getUniqueDirectoryArtifact("_j2objc_pruned", paramFilePath, buildConfiguration.getBinDirectory(ruleContext.getRule().getRepository()));
Artifact prunedJ2ObjcArchive = intermediateArtifacts.j2objcPrunedArchive(j2objcArchive);
Artifact dummyArchive = Iterables.getOnlyElement(ruleContext.getPrerequisite("$dummy_lib", Mode.TARGET, ObjcProvider.class).get(LIBRARY));
CustomCommandLine commandLine = CustomCommandLine.builder().addExecPath("--input_archive", j2objcArchive).addExecPath("--output_archive", prunedJ2ObjcArchive).addExecPath("--dummy_archive", dummyArchive).addExecPath("--xcrunwrapper", xcrunwrapper(ruleContext).getExecutable()).addJoinExecPaths("--dependency_mapping_files", ",", j2ObjcDependencyMappingFiles).addJoinExecPaths("--header_mapping_files", ",", j2ObjcHeaderMappingFiles).addJoinExecPaths("--archive_source_mapping_files", ",", j2ObjcArchiveSourceMappingFiles).add("--entry_classes").add(Joiner.on(",").join(entryClasses)).build();
ruleContext.registerAction(new ParameterFileWriteAction(ruleContext.getActionOwner(), paramFile, commandLine, ParameterFile.ParameterFileType.UNQUOTED, ISO_8859_1));
ruleContext.registerAction(ObjcRuleClasses.spawnAppleEnvActionBuilder(appleConfiguration, appleConfiguration.getSingleArchPlatform()).setMnemonic("DummyPruner").setExecutable(pruner).addInput(dummyArchive).addInput(pruner).addInput(paramFile).addInput(j2objcArchive).addInput(xcrunwrapper(ruleContext).getExecutable()).addTransitiveInputs(j2ObjcDependencyMappingFiles).addTransitiveInputs(j2ObjcHeaderMappingFiles).addTransitiveInputs(j2ObjcArchiveSourceMappingFiles).setCommandLine(CustomCommandLine.builder().addPaths("@%s", paramFile.getExecPath()).build()).addOutput(prunedJ2ObjcArchive).build(ruleContext));
}
}
use of com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction in project bazel by bazelbuild.
the class BazelPythonSemantics method createPythonZipAction.
private static void createPythonZipAction(RuleContext ruleContext, Artifact executable, Artifact zipFile, Artifact templateMain, FilesToRunProvider zipper, RunfilesSupport runfilesSupport) {
NestedSetBuilder<Artifact> inputsBuilder = NestedSetBuilder.stableOrder();
PathFragment workspaceName = runfilesSupport.getWorkspaceName();
CustomCommandLine.Builder argv = new CustomCommandLine.Builder();
inputsBuilder.add(templateMain);
argv.add("__main__.py=" + templateMain.getExecPathString());
// Creating __init__.py files under each directory
argv.add("__init__.py=");
argv.add(getZipRunfilesPath("__init__.py", workspaceName) + "=");
for (String path : runfilesSupport.getRunfiles().getEmptyFilenames()) {
argv.add(getZipRunfilesPath(path, workspaceName) + "=");
}
// Filter the executable file, cause we are building it.
for (Artifact artifact : runfilesSupport.getRunfilesArtifactsWithoutMiddlemen()) {
if (!artifact.equals(executable)) {
argv.add(getZipRunfilesPath(artifact.getRunfilesPath(), workspaceName) + "=" + artifact.getExecPathString());
inputsBuilder.add(artifact);
}
}
// zipper can only consume file list options from param file not other options,
// so write file list in the param file first.
Artifact paramFile = ruleContext.getDerivedArtifact(ParameterFile.derivePath(zipFile.getRootRelativePath()), zipFile.getRoot());
ruleContext.registerAction(new ParameterFileWriteAction(ruleContext.getActionOwner(), paramFile, argv.build(), ParameterFile.ParameterFileType.UNQUOTED, ISO_8859_1));
ruleContext.registerAction(new SpawnAction.Builder().addInput(paramFile).addTransitiveInputs(inputsBuilder.build()).addOutput(zipFile).setExecutable(zipper).useDefaultShellEnvironment().addArgument("cC").addArgument(zipFile.getExecPathString()).addArgument("@" + paramFile.getExecPathString()).setMnemonic("PythonZipper").build(ruleContext));
}
Aggregations