help-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Shell for evaluating .SHELLFLAGS


From: Afif Elghraoui
Subject: Re: Shell for evaluating .SHELLFLAGS
Date: Tue, 26 May 2015 12:35:46 -0700
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Icedove/31.7.0

Hi, Malcolm,

On 05/26/2015 10:16 AM, Cook, Malcolm wrote:
Afif,

Are you trying to get the output from different SQL recipes to go into 
different files.


Yes

This will be a problem when using sqlite3 as your make .SHELL.

Why?  Because the contents of a make recipe is always passed to the .SHELL as a 
parameter.  Never on stdin.  But that is what you need.

Why do you need the recipe on stdin?

Because meta-commands (aka dot commands) such as .output are limited in where 
they can appear.


Right. That's why I pass in the meta-commands using the init file with sqlite3's -i flag.


In particular, that are not understood when they appear in the contents of a 
multi-line string as the SQL parameter to sqlite3 .

So, the workaround to this problem in general is this one line bash utility 
which you use as the .SHELL instead of sqlite3:

#!/bin/env bash
### bash1in: A bash utility script which pipes its last argument to a
### process gained by executing all but its last argument.  Useful in
### Makefiles where you want the recipes to appear on stdin of some
### command other than the usual bash shell.  For example, to write
### recipes in sqlite3 (allowing dot-commands), include the following in your 
Makefile:
###     SHELL=./bash1in
###     .SHELLFLAGS=sqlite3 ${DB}
###     .ONESHELL:  # optional
cat <<< "${@:$#}" | "${@:1:$(($# - 1))}"o


Thanks. That's an interesting way to do it.


Now you can write makefiles like this:

### FILE: sqlite3.test.mk - demonstration of using sqlite3 as
### interpreter of Make recipes using utility bash script (in same
### directory) `bash1in`.

SHELL=./bash1in
.SHELLFLAGS=sqlite3 ${DB}
.ONESHELL:

${DB}:
        CREATE TABLE greeting (g string );
        INSERT INTO greeting values("Hello World");
        INSERT INTO greeting values("Hello sqlite3");

db.out.schema:
        .output $@
        .schema

db.out.select.%:
        .output $@
        select * from $*;


What I have now passes ".output $@" as a shellflag using process substitution to make a dynamic sqlite init file for each recipe, so I don't have to write this for every rule.

Which can be run like this:

make -f sqlite3.test.mk DB=db.t
CREATE TABLE greeting (g string );
INSERT INTO greeting values("Hello World");
INSERT INTO greeting values("Hello sqlite3");
make -f sqlite3.test.mk DB=db.t db.out.select.greeting
.output db.out.select.greeting
select * from greeting;
cat  db.out.select.greeting
Hello World
Hello sqlite3
make -f sqlite3.test.mk DB=db.t db.out.schema
.output db.out.schema
.schema
cat  db.out.schema
CREATE TABLE greeting (g string );

What is nice about this approach is that it works with other interpreters.  
I've used this approach for instance with the R language as the interpreter.

I'll keep that in mind. I've played around with using R as the make SHELL. For that, I was able to get it working by using Rscript rather than R as the shell:

SHELL = /usr/bin/Rscript
.SHELLFLAGS = --vanilla -e

that avoids the need for passing inputs on stdin, but it's good to know how to make it work with stdin.


Many thanks and regards

Afif




reply via email to

[Prev in Thread] Current Thread [Next in Thread]