List of usage examples for com.google.common.collect Iterables cycle
public static <T> Iterable<T> cycle(T... elements)
From source file:com.facebook.buck.haskell.HaskellCompileRule.java
/** * @return the arguments to pass to the compiler to build against package dependencies. *///from w w w . ja v a2 s.c o m private Iterable<String> getPackageArgs() { Set<String> packageDbs = new TreeSet<>(); Set<String> hidden = new TreeSet<>(); Set<String> exposed = new TreeSet<>(); for (HaskellPackage haskellPackage : packages.values()) { packageDbs.add(getResolver().getAbsolutePath(haskellPackage.getPackageDb()).toString()); hidden.add(String.format("%s-%s", haskellPackage.getInfo().getName(), haskellPackage.getInfo().getVersion())); } for (HaskellPackage haskellPackage : exposedPackages.values()) { packageDbs.add(getResolver().getAbsolutePath(haskellPackage.getPackageDb()).toString()); exposed.add(String.format("%s-%s", haskellPackage.getInfo().getName(), haskellPackage.getInfo().getVersion())); } // We add all package DBs, and explicit expose or hide packages depending on whether they are // exposed or not. This allows us to support setups that either add `-hide-all-packages` or // not. return ImmutableList.<String>builder() .addAll(MoreIterables.zipAndConcat(Iterables.cycle("-package-db"), packageDbs)) .addAll(MoreIterables.zipAndConcat(Iterables.cycle("-package"), exposed)) .addAll(MoreIterables.zipAndConcat(Iterables.cycle("-hide-package"), hidden)).build(); }
From source file:com.facebook.buck.features.haskell.HaskellBinaryDescription.java
@Override public BuildRule createBuildRule(BuildRuleCreationContextWithTargetGraph context, BuildTarget buildTarget, BuildRuleParams params, HaskellBinaryDescriptionArg args) { ProjectFilesystem projectFilesystem = context.getProjectFilesystem(); CellPathResolver cellRoots = context.getCellPathResolver(); HaskellPlatform platform = getPlatform(buildTarget, args); ActionGraphBuilder graphBuilder = context.getActionGraphBuilder(); Optional<Type> type = BINARY_TYPE.getValue(buildTarget); // Handle #ghci flavor if (type.isPresent() && type.get() == Type.GHCI) { return HaskellDescriptionUtils.requireGhciRule(buildTarget, projectFilesystem, params, cellRoots, graphBuilder, platform, cxxBuckConfig, args.getDeps(), args.getPlatformDeps(), args.getSrcs(), args.getGhciPreloadDeps(), args.getGhciPlatformPreloadDeps(), args.getCompilerFlags(), Optional.empty(), Optional.empty(), ImmutableList.of(), args.isEnableProfiling()); }/*www. jav a2s . c o m*/ SourcePathRuleFinder ruleFinder = new SourcePathRuleFinder(graphBuilder); SourcePathResolver pathResolver = DefaultSourcePathResolver.from(ruleFinder); Linker.LinkableDepType depType = getLinkStyle(args, type); // The target to use for the link rule. BuildTarget binaryTarget = buildTarget.withFlavors(InternalFlavor.of("binary")); // Maintain backwards compatibility to ease upgrade flows. if (platform.shouldUsedOldBinaryOutputLocation().orElse(true)) { binaryTarget = binaryTarget.withAppendedFlavors(platform.getFlavor()); } ImmutableSet.Builder<BuildRule> depsBuilder = ImmutableSet.builder(); depsBuilder.addAll(CxxDeps.builder().addDeps(args.getDeps()).addPlatformDeps(args.getPlatformDeps()).build() .get(graphBuilder, platform.getCxxPlatform())); ImmutableList<BuildRule> depQueryDeps = args.getDepsQuery() .map(query -> Objects.requireNonNull(query.getResolvedQuery()).stream().map(graphBuilder::getRule) .filter(NativeLinkable.class::isInstance)) .orElse(Stream.of()).collect(ImmutableList.toImmutableList()); depsBuilder.addAll(depQueryDeps); ImmutableSet<BuildRule> deps = depsBuilder.build(); // Inputs we'll be linking (archives, objects, etc.) ImmutableList.Builder<Arg> linkInputsBuilder = ImmutableList.builder(); // Additional linker flags passed to the Haskell linker ImmutableList.Builder<Arg> linkFlagsBuilder = ImmutableList.builder(); CommandTool.Builder executableBuilder = new CommandTool.Builder(); // Add the binary as the first argument. executableBuilder.addArg(SourcePathArg.of(DefaultBuildTargetSourcePath.of(binaryTarget))); Path outputDir = BuildTargetPaths.getGenPath(projectFilesystem, binaryTarget, "%s").getParent(); Path outputPath = outputDir.resolve(binaryTarget.getShortName()); Path absBinaryDir = buildTarget.getCellPath().resolve(outputDir); // Special handling for dynamically linked binaries. if (depType == Linker.LinkableDepType.SHARED) { // Create a symlink tree with for all shared libraries needed by this binary. SymlinkTree sharedLibraries = graphBuilder.addToIndex( CxxDescriptionEnhancer.createSharedLibrarySymlinkTree(buildTarget, projectFilesystem, graphBuilder, ruleFinder, platform.getCxxPlatform(), deps, r -> Optional.empty())); // Embed a origin-relative library path into the binary so it can find the shared libraries. // The shared libraries root is absolute. Also need an absolute path to the linkOutput linkFlagsBuilder.addAll(StringArg.from(MoreIterables.zipAndConcat(Iterables.cycle("-optl"), Linkers.iXlinker("-rpath", String.format("%s/%s", platform.getCxxPlatform().getLd().resolve(graphBuilder).origin(), absBinaryDir.relativize(sharedLibraries.getRoot()).toString()))))); // Add all the shared libraries and the symlink tree as inputs to the tool that represents // this binary, so that users can attach the proper deps. executableBuilder.addNonHashableInput(sharedLibraries.getRootSourcePath()); executableBuilder.addInputs(sharedLibraries.getLinks().values()); } // Add in linker flags. linkFlagsBuilder.addAll(ImmutableList.copyOf(Iterables.transform(args.getLinkerFlags(), f -> CxxDescriptionEnhancer.toStringWithMacrosArgs(buildTarget, cellRoots, graphBuilder, platform.getCxxPlatform(), f)))); // Generate the compile rule and add its objects to the link. HaskellCompileRule compileRule = graphBuilder.addToIndex(HaskellDescriptionUtils.requireCompileRule( buildTarget, projectFilesystem, params, graphBuilder, ruleFinder, RichStream.from(deps) .filter(dep -> dep instanceof HaskellCompileDep || dep instanceof CxxPreprocessorDep) .toImmutableSet(), platform, depType, args.isEnableProfiling(), args.getMain(), Optional.empty(), args.getCompilerFlags(), HaskellSources.from(buildTarget, graphBuilder, pathResolver, ruleFinder, platform, "srcs", args.getSrcs()))); linkInputsBuilder.addAll(SourcePathArg.from(compileRule.getObjects())); ImmutableList<Arg> linkInputs = linkInputsBuilder.build(); ImmutableList<Arg> linkFlags = linkFlagsBuilder.build(); CommandTool executable = executableBuilder.build(); HaskellLinkRule linkRule = HaskellDescriptionUtils.createLinkRule(binaryTarget, projectFilesystem, params, graphBuilder, ruleFinder, platform, Linker.LinkType.EXECUTABLE, linkFlags, linkInputs, RichStream.from(deps).filter(NativeLinkable.class).toImmutableList(), args.getLinkDepsQueryWhole() ? RichStream.from(depQueryDeps).map(BuildRule::getBuildTarget).toImmutableSet() : ImmutableSet.of(), depType, outputPath, Optional.empty(), args.isEnableProfiling()); return new HaskellBinary(buildTarget, projectFilesystem, params.copyAppendingExtraDeps(linkRule), deps, executable, linkRule.getSourcePathToOutput()); }
From source file:com.facebook.buck.haskell.HaskellCompileRule.java
private Iterable<String> getPreprocessorFlags() { CxxToolFlags cxxToolFlags = ppFlags.toToolFlags(getResolver(), PathShortener.identity(), CxxDescriptionEnhancer.frameworkPathToSearchPath(cxxPlatform, getResolver()), preprocessor, /* pch */ Optional.empty()); return MoreIterables.zipAndConcat(Iterables.cycle("-optP"), cxxToolFlags.getAllFlags()); }
From source file:com.facebook.buck.features.haskell.HaskellCompileRule.java
/** @return the arguments to pass to the compiler to build against package dependencies. */ private Iterable<String> getPackageArgs(SourcePathResolver resolver) { Set<String> packageDbs = new TreeSet<>(); Set<String> hidden = new TreeSet<>(); Set<String> exposed = new TreeSet<>(); for (HaskellPackage haskellPackage : packages.values()) { packageDbs.add(resolver.getAbsolutePath(haskellPackage.getPackageDb()).toString()); hidden.add(String.format("%s-%s", haskellPackage.getInfo().getName(), haskellPackage.getInfo().getVersion())); }/* www .j av a2s .c o m*/ for (HaskellPackage haskellPackage : exposedPackages.values()) { packageDbs.add(resolver.getAbsolutePath(haskellPackage.getPackageDb()).toString()); exposed.add(String.format("%s-%s", haskellPackage.getInfo().getName(), haskellPackage.getInfo().getVersion())); } // We add all package DBs, and explicit expose or hide packages depending on whether they are // exposed or not. This allows us to support setups that either add `-hide-all-packages` or // not. return ImmutableList.<String>builder() .addAll(MoreIterables.zipAndConcat(Iterables.cycle("-package-db"), packageDbs)) .addAll(MoreIterables.zipAndConcat(Iterables.cycle("-package"), exposed)) .addAll(MoreIterables.zipAndConcat(Iterables.cycle("-hide-package"), hidden)).build(); }
From source file:com.facebook.buck.features.haskell.HaskellCompileRule.java
private Iterable<String> getPreprocessorFlags(SourcePathResolver resolver) { CxxToolFlags cxxToolFlags = ppFlags.toToolFlags(resolver, PathShortener.identity(), CxxDescriptionEnhancer.frameworkPathToSearchPath(cxxPlatform, resolver), preprocessor, /* pch */ Optional.empty()); return MoreIterables.zipAndConcat(Iterables.cycle("-optP"), Arg.stringify(cxxToolFlags.getAllFlags(), resolver)); }
From source file:com.eucalyptus.util.async.Futures.java
/** * TODO:GUAVA: remove and use the method available in Guava 10 *///from w w w. j a va 2 s . c o m public static <R> CheckedListenableFuture<List<R>> allAsList(final List<CheckedListenableFuture<R>> futures) { final GenericCheckedListenableFuture<List<R>> combined = new GenericCheckedListenableFuture<List<R>>(); final List<R> resultList = Lists.newArrayListWithCapacity(futures.size()); Iterables.addAll(resultList, Iterables.limit(Iterables.cycle((R) null), futures.size())); final AtomicInteger completionCountdown = new AtomicInteger(futures.size()); for (int i = 0; i < futures.size(); i++) { final int resultIndex = i; final CheckedListenableFuture<R> future = futures.get(i); future.addListener(new Runnable() { @Override public void run() { try { resultList.set(resultIndex, future.get()); } catch (final ExecutionException e) { combined.setException(e.getCause()); } catch (CancellationException e) { combined.cancel(false); } catch (InterruptedException e) { // complete so can't happen } if (completionCountdown.decrementAndGet() == 0) { combined.set(resultList); } } }); } return combined; }
From source file:com.facebook.buck.features.haskell.HaskellDescriptionUtils.java
/** * Create a Haskell link rule that links the given inputs to a executable or shared library and * pulls in transitive native linkable deps from the given dep roots. *///from w w w. j a v a 2s . c o m public static HaskellLinkRule createLinkRule(BuildTarget target, ProjectFilesystem projectFilesystem, BuildRuleParams baseParams, ActionGraphBuilder graphBuilder, SourcePathRuleFinder ruleFinder, HaskellPlatform platform, Linker.LinkType linkType, ImmutableList<Arg> linkerFlags, Iterable<Arg> linkerInputs, Iterable<? extends NativeLinkable> deps, ImmutableSet<BuildTarget> linkWholeDeps, Linker.LinkableDepType depType, Path outputPath, Optional<String> soname, boolean hsProfile) { Tool linker = platform.getLinker().resolve(graphBuilder); ImmutableList.Builder<Arg> linkerArgsBuilder = ImmutableList.builder(); ImmutableList.Builder<Arg> argsBuilder = ImmutableList.builder(); // Add the base flags from the `.buckconfig` first. argsBuilder.addAll(StringArg.from(platform.getLinkerFlags())); // Pass in the appropriate flags to link a shared library. if (linkType.equals(Linker.LinkType.SHARED)) { argsBuilder.addAll(StringArg.from("-shared", "-dynamic")); soname.ifPresent( name -> argsBuilder.addAll(StringArg.from(MoreIterables.zipAndConcat(Iterables.cycle("-optl"), platform.getCxxPlatform().getLd().resolve(graphBuilder).soname(name))))); } // Add in extra flags passed into this function. argsBuilder.addAll(linkerFlags); // We pass in the linker inputs and all native linkable deps by prefixing with `-optl` so that // the args go straight to the linker, and preserve their order. linkerArgsBuilder.addAll(linkerInputs); for (NativeLinkable nativeLinkable : NativeLinkables.getNativeLinkables(platform.getCxxPlatform(), graphBuilder, deps, depType)) { NativeLinkable.Linkage link = nativeLinkable.getPreferredLinkage(platform.getCxxPlatform(), graphBuilder); NativeLinkableInput input = nativeLinkable.getNativeLinkableInput(platform.getCxxPlatform(), NativeLinkables.getLinkStyle(link, depType), linkWholeDeps.contains(nativeLinkable.getBuildTarget()), graphBuilder); linkerArgsBuilder.addAll(input.getArgs()); } // Since we use `-optl` to pass all linker inputs directly to the linker, the haskell linker // will complain about not having any input files. So, create a dummy archive with an empty // module and pass that in normally to work around this. BuildTarget emptyModuleTarget = target.withAppendedFlavors(InternalFlavor.of("empty-module")); WriteFile emptyModule = graphBuilder .addToIndex(new WriteFile(emptyModuleTarget, projectFilesystem, "module Unused where", BuildTargetPaths.getGenPath(projectFilesystem, emptyModuleTarget, "%s/Unused.hs"), /* executable */ false)); HaskellCompileRule emptyCompiledModule = graphBuilder.addToIndex(createCompileRule( target.withAppendedFlavors(InternalFlavor.of("empty-compiled-module")), projectFilesystem, baseParams, graphBuilder, ruleFinder, // TODO(agallagher): We shouldn't need any deps to compile an empty module, but ghc // implicitly tries to load the prelude and in some setups this is provided via a // Buck dependency. RichStream.from(deps).filter(BuildRule.class).toImmutableSortedSet(Ordering.natural()), platform, depType, hsProfile, Optional.empty(), Optional.empty(), ImmutableList.of(), HaskellSources.builder().putModuleMap("Unused", emptyModule.getSourcePathToOutput()).build())); BuildTarget emptyArchiveTarget = target.withAppendedFlavors(InternalFlavor.of("empty-archive")); Archive emptyArchive = graphBuilder.addToIndex(Archive.from(emptyArchiveTarget, projectFilesystem, graphBuilder, ruleFinder, platform.getCxxPlatform(), BuildTargetPaths.getGenPath(projectFilesystem, emptyArchiveTarget, "%s/libempty.a"), emptyCompiledModule.getObjects(), /* cacheable */ true)); argsBuilder.add(SourcePathArg.of(emptyArchive.getSourcePathToOutput())); ImmutableList<Arg> args = argsBuilder.build(); ImmutableList<Arg> linkerArgs = linkerArgsBuilder.build(); return graphBuilder.addToIndex(new HaskellLinkRule(target, projectFilesystem, baseParams .withDeclaredDeps(ImmutableSortedSet.<BuildRule>naturalOrder() .addAll(BuildableSupport.getDepsCollection(linker, ruleFinder)) .addAll(Stream.of(args, linkerArgs).flatMap(Collection::stream) .flatMap(arg -> BuildableSupport.getDeps(arg, ruleFinder)).iterator()) .build()) .withoutExtraDeps(), linker, outputPath, args, linkerArgs, platform.shouldCacheLinks())); }
From source file:com.facebook.buck.haskell.HaskellCompileRule.java
@Override public ImmutableList<Step> getBuildSteps(BuildContext context, BuildableContext buildableContext) { buildableContext.recordArtifact(getObjectDir()); buildableContext.recordArtifact(getInterfaceDir()); buildableContext.recordArtifact(getStubDir()); return ImmutableList.of(new MakeCleanDirectoryStep(getProjectFilesystem(), getObjectDir()), new MakeCleanDirectoryStep(getProjectFilesystem(), getInterfaceDir()), new MakeCleanDirectoryStep(getProjectFilesystem(), getStubDir()), new ShellStep(getProjectFilesystem().getRootPath()) { @Override/*from w w w.j a v a 2 s . co m*/ public ImmutableMap<String, String> getEnvironmentVariables(ExecutionContext context) { return ImmutableMap.<String, String>builder().putAll(super.getEnvironmentVariables(context)) .putAll(compiler.getEnvironment()).build(); } @Override protected ImmutableList<String> getShellCommandInternal(ExecutionContext context) { return ImmutableList.<String>builder().addAll(compiler.getCommandPrefix(getResolver())) .addAll(flags).add("-no-link") .addAll(picType == CxxSourceRuleFactory.PicType.PIC ? ImmutableList.of("-dynamic", "-fPIC", "-hisuf", "dyn_hi") : ImmutableList.of()) .addAll(MoreIterables.zipAndConcat(Iterables.cycle("-main-is"), OptionalCompat.asSet(main))) .addAll(getPackageNameArgs()).addAll(getPreprocessorFlags()) .add("-odir", getProjectFilesystem().resolve(getObjectDir()).toString()) .add("-hidir", getProjectFilesystem().resolve(getInterfaceDir()).toString()) .add("-stubdir", getProjectFilesystem().resolve(getStubDir()).toString()) .add("-i" + includes.stream().map(getResolver()::getAbsolutePath) .map(Object::toString).collect(Collectors.joining(":"))) .addAll(getPackageArgs()).addAll(sources.getSourcePaths().stream() .map(getResolver()::getAbsolutePath).map(Object::toString).iterator()) .build(); } @Override public String getShortName() { return "haskell-compile"; } }); }
From source file:com.facebook.buck.ocaml.OCamlBuildContext.java
private static ImmutableList<String> addPrefix(String prefix, Iterable<String> flags) { return ImmutableList.copyOf(MoreIterables.zipAndConcat(Iterables.cycle(prefix), flags)); }
From source file:com.facebook.buck.haskell.HaskellGhciRule.java
@Override public ImmutableList<Step> getBuildSteps(BuildContext context, BuildableContext buildableContext) { SourcePathResolver resolver = context.getSourcePathResolver(); String name = getBuildTarget().getShortName(); Path dir = getOutputDir();/* www .ja va2s. c om*/ Path so = resolver.getRelativePath(omnibusSharedObject.getSourcePathToOutput()); Path packagesDir = dir.resolve(name + ".packages"); Path symlinkDir = dir.resolve(name + ".so-symlinks"); ImmutableList.Builder<Step> steps = ImmutableList.builder(); steps.addAll(MakeCleanDirectoryStep.of(BuildCellRelativePath .fromCellRelativePath(context.getBuildCellRootPath(), getProjectFilesystem(), dir))); steps.addAll(MakeCleanDirectoryStep.of(BuildCellRelativePath .fromCellRelativePath(context.getBuildCellRootPath(), getProjectFilesystem(), symlinkDir))); steps.addAll(MakeCleanDirectoryStep.of(BuildCellRelativePath .fromCellRelativePath(context.getBuildCellRootPath(), getProjectFilesystem(), packagesDir))); steps.add(CopyStep.forFile(getProjectFilesystem(), so, dir.resolve(so.getFileName()))); try { for (Map.Entry<String, SourcePath> ent : solibs.entrySet()) { Path src = resolver.getRelativePath(ent.getValue()).toRealPath(); Path dest = symlinkDir.resolve(ent.getKey()); steps.add(SymlinkFileStep.builder().setFilesystem(getProjectFilesystem()).setExistingFile(src) .setDesiredLink(dest).build()); } } catch (IOException ex) { throw new RuntimeException(ex); } ImmutableSet.Builder<String> pkgdirs = ImmutableSet.builder(); for (HaskellPackage pkg : prebuiltHaskellPackages) { try { pkgdirs.add(resolver.getRelativePath(pkg.getPackageDb()).toRealPath().toString()); } catch (IOException ex) { throw new RuntimeException(ex); } } for (HaskellPackage pkg : haskellPackages) { String pkgname = pkg.getInfo().getName(); Path pkgdir = packagesDir.resolve(pkgname); steps.addAll(MakeCleanDirectoryStep.of(BuildCellRelativePath .fromCellRelativePath(context.getBuildCellRootPath(), getProjectFilesystem(), pkgdir))); Path pkgDbSrc = resolver.getRelativePath(pkg.getPackageDb()); steps.add(CopyStep.forDirectory(getProjectFilesystem(), pkgDbSrc, pkgdir, CopyStep.DirectoryMode.DIRECTORY_AND_CONTENTS)); ImmutableSet.Builder<Path> artifacts = ImmutableSet.builder(); for (SourcePath lib : pkg.getLibraries()) { artifacts.add(resolver.getRelativePath(lib).getParent()); } // this is required because the .a files above are thin archives, // they merely point to the .o files via a relative path. for (SourcePath obj : pkg.getObjects()) { artifacts.add(resolver.getRelativePath(obj).getParent()); } for (SourcePath iface : pkg.getInterfaces()) { artifacts.add(resolver.getRelativePath(iface).getParent()); } for (Path artifact : artifacts.build()) { steps.add(CopyStep.forDirectory(getProjectFilesystem(), artifact, pkgdir, CopyStep.DirectoryMode.DIRECTORY_AND_CONTENTS)); } pkgdirs.add("${DIR}/" + dir.relativize(pkgdir.resolve(pkgDbSrc.getFileName())).toString()); } ImmutableSet.Builder<String> exposedPkgs = ImmutableSet.builder(); for (HaskellPackage pkg : firstOrderHaskellPackages) { exposedPkgs.add(String.format("%s-%s", pkg.getInfo().getName(), pkg.getInfo().getVersion())); } StringBuilder startGhciContents = new StringBuilder(); startGhciContents.append(":set "); startGhciContents.append(Joiner.on(' ').join(ImmutableList.<String>builder() .addAll(MoreIterables.zipAndConcat(Iterables.cycle("-package"), exposedPkgs.build())).build())); if (ghciInit.isPresent()) { try { startGhciContents.append('\n'); List<String> lines = Files.readAllLines(resolver.getRelativePath(ghciInit.get()), StandardCharsets.UTF_8); startGhciContents.append(Joiner.on('\n').join(lines)); } catch (IOException ex) { throw new RuntimeException(ex); } } Path startGhci = dir.resolve("start.ghci"); steps.add(new WriteFileStep(getProjectFilesystem(), startGhciContents.toString(), startGhci, /* executable */ false)); ImmutableList.Builder<String> srcpaths = ImmutableList.builder(); for (SourcePath sp : srcs.getSourcePaths()) { srcpaths.add(resolver.getRelativePath(sp).toString()); } String ghcPath = null; try { if (ghciBinDep.isPresent()) { Path binDir = dir.resolve(name + ".bin"); Path bin = binDir.resolve("ghci"); BuildRule rule = buildRuleResolver.getRule(ghciBinDep.get()); SourcePath sp = rule.getSourcePathToOutput(); steps.addAll(MakeCleanDirectoryStep.of(BuildCellRelativePath .fromCellRelativePath(context.getBuildCellRootPath(), getProjectFilesystem(), binDir))); steps.add(CopyStep.forFile(getProjectFilesystem(), resolver.getRelativePath(sp), bin)); ghcPath = "${DIR}/" + dir.relativize(bin).toString() + " -B" + ghciLib.toRealPath(); } else { ghcPath = ghciGhc.toRealPath().toString(); } } catch (IOException ex) { throw new RuntimeException(ex); } String pkgdbs = Joiner.on(' ').join(ImmutableList.<String>builder() .addAll(MoreIterables.zipAndConcat(Iterables.cycle("-package-db"), pkgdirs.build())).build()); String exposed = Joiner.on(' ') .join(ImmutableList.<String>builder() .addAll(MoreIterables.zipAndConcat(Iterables.cycle("-expose-package"), exposedPkgs.build())) .build()); if (enableProfiling) { compilerFlags = ImmutableList .copyOf(Iterables.concat(compilerFlags, HaskellDescriptionUtils.PROF_FLAGS)); } String ghc = ghcPath; ImmutableMap.Builder<String, String> templateArgs = ImmutableMap.builder(); try { templateArgs.put("name", name); templateArgs.put("start_ghci", dir.relativize(startGhci).toString()); templateArgs.put("ld_library_path", dir.relativize(symlinkDir).toString()); templateArgs.put("exposed_packages", exposed); templateArgs.put("package_dbs", pkgdbs); templateArgs.put("compiler_flags", Joiner.on(' ').join(compilerFlags)); templateArgs.put("srcs", Joiner.on(' ').join(srcpaths.build())); templateArgs.put("squashed_so", dir.relativize(dir.resolve(so.getFileName())).toString()); templateArgs.put("binutils_path", ghciBinutils.toRealPath().toString()); templateArgs.put("ghc_path", ghc); templateArgs.put("cxx_path", ghciCxx.toRealPath().toString()); templateArgs.put("cc_path", ghciCc.toRealPath().toString()); templateArgs.put("cpp_path", ghciCpp.toRealPath().toString()); } catch (IOException ex) { throw new RuntimeException(ex); } Path script = dir.resolve(name); steps.add(new StringTemplateStep(ghciScriptTemplate, getProjectFilesystem(), script, templateArgs.build())); steps.add(new MakeExecutableStep(getProjectFilesystem(), script)); return steps.build(); }