Hi Pants team, I'm evaluating the migration from BUCK to Pants, as your Python support is much better. However, there are a couple of things I still don't know how to do.
I'm trying to define a set of helper functions and to define custom target types. The latter is the most important feature we need as we would need for example to compile C extensions, cython, package an app with a different format (like for appengine), compile/minify javascript among other tasks.
In BUCK
there are two concepts that make extending it quite easy. These are genrule
which allows you to define a new target rule that calls an executable and include_defs
which allows to easily include those macro definitions. Additionally, in the configuration one can specify which macro files will be included before parsing each BUILD
file.
Ideally I'm looking for a solution which does not require to modify Pants' sources.
> Syntax suggestions are welcome, we'll miss the mark without them.
I think the first step is to get everyone on the same page by answering some basic questions:
How do you run multiple lines of shell script?
How do you handle errors?
How do you interpolate Python data?
How do you make sure the interpolated Python data is safe given it might contain things like "; rm -rf /"?
Is it possible to use shells other than bash?
Is there a way to configure dependencies so that the shell commands don't have to get re-run in cases where it's unnecessary? For instance, should the shell command create a file that can be stat-ed and compared to other files? Do you need to configure the source files used by the shell command?
Given the above, what's the syntax?
Here's my first pass at some answers:
> How do you run multiple lines of shell script?
You pass it in a triple quoted string in the BUILD file. The triple quoted string gets written to a temporary shell script and executed.
> How do you handle errors?
The shell script should be run with -e by default.
> How do you interpolate Python data?
Via the normal Python mechanism.
> How do you make sure the interpolated Python data is safe given it might contain things like "; rm -rf /"?
There should be a helper function exposed by default and well documented. See pipes.quote or shlex.quote (http://docs.python.org/2/library/pipes.html).
> Is it possible to use shells other than bash?
Yes. One of the keyword arguments should be shebang="#!/usr/bin/env bash -e". This lets the user configure how the script should be run.
> Is there a way to configure dependencies so that the shell commands don't have to get re-run in cases where it's unnecessary? For instance, should the shell command create a file that can be stat-ed and compared to other files? Do you need to configure the source files used by the shell command?
If the user configures sources=some_list_of_files and target=some_file, the system can use stat to avoid re-executing the shell script in some cases (the same way make would). If the user doesn't configure those things, the shell script will get re-evaluated every time the pants target is used as a dependency (the way make works if you don't specify a target file).
> Given the above, what's the syntax?
How about:
shell_script(name = 'some_name', script = """ for i in $( find . -name \*.nnn ); do nnn_processor < $i > $i.mmm done mmm_processor $( find . -name \*.mmm ) -o some_file """, sources = rglobs('*.nnn'), # If this is left to the default of None, perhaps the system can touch # a temporary file to know whether that file is newer than any *.nnn file. target = "some_file", # shell_scripts can depend on each other. # dependencies = [], # This is the default. # shebang="#!/usr/bin/env bash -e" )