tonyfischetti/sake — pull request #8 by kirbyfan64 (2014-02-07 02:26:55+00:00)
Title: Use string templates for macros

There's one problem with Sake's macro system. Say I have a file named test.c:

```c
#define STR_EXPAND(s) #s
#define STR(s) STR_EXPAND(s)
#define PATH STR(sys_path)
#include

int main()
{
puts(PATH);
}
```

It basically prints the contents of the PATH macro. Now, say I want it defined at compile-time using GCC's -D flag. Here's my Sakefile:

```yaml
#! PATH=.
# ^ just in case we move the project around

do something cool:
help: ...
dependencies:
- $PATH/test.o
output:
- $PATH/test
formula: >
clang $PATH/test.o -o $PATH/test
# Use our PATH macro

do someting cool with the PATH environment variable:
help: ...
dependencies:
- $PATH/test.c
output:
- $PATH/test.o
# We need the normal PATH variable as a macro definition
formula: >
clang -c -Dsys_path=$PATH $PATH/test.c -o $PATH/test.o
# ^whoops!
```

See the issue? I meant to refer to the PATH environment variable, but it instead refers to the PATH macro. Now, even if I notice the issue, the only real solution is to change the macro name. If I use that macro, say, 100 times, it might take a while to change!

What does this have to do with Python's string templates? Well, using the templates lets me do this:

```yaml
#! PATH=.
# ^ just in case we move the project around

do something cool:
help: ...
dependencies:
- $PATH/test.o
output:
- $PATH/test
formula: >
clang $PATH/test.o -o $PATH/test
# Use our PATH macro

do someting cool with the PATH environment variable:
help: ...
dependencies:
- $PATH/test.c
output:
- $PATH/test.o
# We need the normal PATH variable as a macro definition
formula: >
clang -c -Dsys_path=$$PATH $PATH/test.c -o $PATH/test.o
# ^works!
```

Notice the `$$`. String templates let you escape dollar signs. They are also much simpler to maintain.