Have you ever had that lingering question of:
If you do much work with GNU/Make, you've probably seen some projects specifically use /bin/bash instead of /bin/sh. But outside of that, maybe you've never seen SHELL set to anything else.
I have two new favorite features in GNU/Make 3.82:
This example doesn't show my two new favorite GNU/Make features, but it's a great example of why I like them!
One thing to note with this example is that the default option passed to the $(SHELL) is '-c', which... luckily is the right option to pass python to execute a command on the python command-line! If we used GNU/Make 3.81 and wanted to use perl instead of python, there would be no way of setting '-e' or '-E' on the perl command-line to say that what is in the recipe of the Makefile are not files themselves, but commands to execute (like one-liner's). So in this episode, I'm not going to go much into .SHELLFLAGS.
Another thing to note about this example is that the whole recipe is on one line! If we wanted to break it up on multiple lines, we could do it this way:
Great! But, this is still hellishly ugly! All those semi-colons and back slashes are ugly and error prone to seasoned python developers.
Enter .ONESHELL:
Awesome! Instead of the interpreter executing and exiting for each line of the recipe, it runs the entire recipe with one instance.
Now, it would be great to not see the commands when we run make! I noticed when I add the '@' character to just the first line in the recipe, it silences the whole recipe, so now we have:
And this make sense, because with .ONESHELL set, the whole recipe is being ran by the same interpreter instance.
I know the examples here aren't exactly mind blowing, but I didn't see a whole lot of documentation on using other interpreters with $(SHELL) on GNU/Make. Hopefully this is helpful to someone!
EDIT: One last thing to note, if you are new to using GNU/Make, the lines before the recipe start with tabs, not 8 spaces! This can also be changed with the new feature .RECIPEPREFIX:
Enjoy!
What else can I do with the SHELL environment variable in GNU/Make?Well, I did and tried a few different little tests and figured I'd share them with you.
If you do much work with GNU/Make, you've probably seen some projects specifically use /bin/bash instead of /bin/sh. But outside of that, maybe you've never seen SHELL set to anything else.
I have two new favorite features in GNU/Make 3.82:
- .SHELLFLAGS
- .ONESHELL:
The argument(s) passed to the shell are taken from the variable.ONESHELL:.SHELLFLAGS
. The default value of.SHELLFLAGS
is-c
normally, or-ec
in POSIX-conforming mode.
Sometimes you would prefer that all the lines in the recipe be passed to a single invocation of the shell.Lets have some fun! Lets say instead of using a posix shell for our Makefile recipe, lets use Python instead!
SHELL = /usr/bin/python .PHONY: all clean all: f = open("hello.txt", "w"); f.write("Hello, World!\n"); f.close() clean: import os; os.remove("hello.txt")
One thing to note with this example is that the default option passed to the $(SHELL) is '-c', which... luckily is the right option to pass python to execute a command on the python command-line! If we used GNU/Make 3.81 and wanted to use perl instead of python, there would be no way of setting '-e' or '-E' on the perl command-line to say that what is in the recipe of the Makefile are not files themselves, but commands to execute (like one-liner's). So in this episode, I'm not going to go much into .SHELLFLAGS.
Another thing to note about this example is that the whole recipe is on one line! If we wanted to break it up on multiple lines, we could do it this way:
SHELL = /usr/bin/python .PHONY: all clean all: f = open("hello.txt", "w"); \ f.write("Hello, World!\n"); \ f.close() clean: import os; \ os.remove("hello.txt")
Enter .ONESHELL:
.ONESHELL: SHELL = /usr/bin/python .PHONY: all clean all: f = open("hello.txt", "w") f.write("Hello, World!\n") f.close() clean: import os os.remove("hello.txt")
Now, it would be great to not see the commands when we run make! I noticed when I add the '@' character to just the first line in the recipe, it silences the whole recipe, so now we have:
.ONESHELL: SHELL = /usr/bin/python .PHONY: all clean all: @f = open("hello.txt", "w") f.write("Hello, World!\n") f.close() clean: @import os os.remove("hello.txt")
I know the examples here aren't exactly mind blowing, but I didn't see a whole lot of documentation on using other interpreters with $(SHELL) on GNU/Make. Hopefully this is helpful to someone!
EDIT: One last thing to note, if you are new to using GNU/Make, the lines before the recipe start with tabs, not 8 spaces! This can also be changed with the new feature .RECIPEPREFIX:
.ONESHELL: .RECIPEPREFIX=> SHELL = /usr/bin/python .PHONY: all clean all: >@f = open("hello.txt", "w") >f.write("Hello, World!\n") >f.close() clean: >@import os >os.remove("hello.txt")
Comments
Post a Comment