[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