内容简介:Did you know that you can change the shell in aNow typingWhat else is possible? Can I use other programming languages as the shell? Is it possible to write in-line Python in a
Did you know that you can change the shell in a Makefile
? It’s true. I found
this out when trying to use bash instead of the default /bin/sh
by setting SHELL
.
.ONESHELL:
bash: SHELL := bash
bash:
# note: the double dollar-sign is required because Make substitues $variables
export greeting="¡hola"
echo "$${greeting}, bash!"
Now typing make bash
will print ¡hola, bash!
What else is possible? Can I use other programming languages as the shell? Is
it possible to write in-line Python in a Makefile
?
Python
.ONESHELL:
python: SHELL := python3
python:
greeting = "hello"
print(f"{greeting}, python!")
Typing make python
will print hello, python!
.
Notice that there is a variable .ONESHELL
being set. Normally, make
will
evaluate each command in a separate shell meaning that, in this example, greeting
would be undefined in the second line. Adding .ONESHELL
to the top
of your Makefile
, as recommended by
someone else whose last name begins with
Davis-* and blogs about make
,
causes multi-line code in the Make directive to be evaluated in a single call
to Python.
R
What about writing R in-line in a Makefile? Note the addition of .SHELLFLAGS
.
By default, make
runs SHELL -c "your\nscript\nhere"
which is not compatible
R. To run a script in-line from a command in R, you use -e
:
R: .SHELLFLAGS := -e R: SHELL := Rscript R: greeting = "bonjour" message(paste0(greeting, ", R!"))
This is equivalent to running Rscript -e 'greeting = "bounjour"; message(paste0(greeting, ", R!"));'
Now you can write a pipeline that combines R and Python in a single file :tada:
Bring in the containers
Data analysis pipelines often have adventurous
dependencies. Docker made all of that a lot easier but writing docker run ...
can be cumbersome. What if we could make Docker the interpreter and write
commands to be executed inside the container in-line as well?
docker: .SHELLFLAGS = run --volume $(shell pwd):/workdir --rm --workdir /workdir --entrypoint /bin/bash ubuntu -c docker: SHELL := docker docker: echo "hello, $$(uname -a)!"
Again, this is possible. Running make docker
will run echo ...
in a Docker
container running Ubuntu. Note the --volume
flag which will mount the current
working directory as the container’s working directory meaning that files can
be read/created between your local filesystem and that of the container. So
build artifacts can be shared between make directives.
hello, Linux 453c728113d6 4.19.76-linuxkit #1 SMP Fri Apr 3 15:53:26 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux!
Why?
This started as an experiment to see what is possible with make
. But it was
motivated by a real world problem: I often need to combine tools across
programming languages and environments to run data analysis pipelines. I like
to automate things and make
is a great tool for doing so. Having everything
in-line is more readable and having everything in a single file means that I
have to jump between fewer tabs to understand the pipeline itself.
The ability to write commands that get executed in Docker means that I have to spend less time figuring out how to get a bunch of dependencies installed in a single container which becomes increasingly difficult as the number of dependencies increases (especially if you work in Bioinformatics).
Full Makefile
note: Some of these features only work on make 4.+
which I installed
using Homebrew
. These examples do not work using make 3.x
which is comes with macOS Catalina.
.ONESHELL:
.SILENT:
main: \
python \
ruby \
R \
bash \
docker
docker: .SHELLFLAGS = run --rm --entrypoint /bin/bash ubuntu -c
docker: SHELL := docker
docker:
echo "hello, $$(uname -a)!"
python: SHELL := python3
python:
greeting = "hello"
print(f"{greeting}, python!")
ruby: .SHELLFLAGS := -e
ruby: SHELL := ruby
ruby:
greeting = "labas"
puts "#{greeting}, ruby!"
R: .SHELLFLAGS := -e
R: SHELL := Rscript
R:
greeting = "bonjour"
message(paste0(greeting, ", R!"))
bash: .SHELLFLAGS := -euo pipefail -c
bash: SHELL := bash
bash:
export greeting="¡hola"
echo "$${greeting}, bash!"
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Beginning ASP.NET 4 in C# and Vb
Imar Spaanjaars / Wrox / 2010-3-19 / GBP 29.99
This book is for anyone who wants to learn how to build rich and interactive web sites that run on the Microsoft platform. With the knowledge you gain from this book, you create a great foundation to ......一起来看看 《Beginning ASP.NET 4 in C# and Vb》 这本书的介绍吧!