How to send input on stdin to a python script defined inside a Makefile?
For me the easiest way to circumvent all the command line quoting problems is to write the code to a file with GNUmake's $(file )
function. You can even use #
as Python comment inside of define
d variables:
VERSION := $(shell bash --version)
# With this, you can use any form of quotes inside your python code
define PYTHON_VERSION_CODE :=
# -*- coding: iso-8859-15 -*-
import re, sys;
program_version = "${VERSION}"
match = re.search("Copyright[^\d]+(\d+)", program_version);
if match:
if int( match.group(1) ) >= 2018:
sys.stdout.write("1")
else:
sys.stdout.write( "match:" + match.group(1) )
else:
sys.stdout.write("0")
endef
$(file > test.py,$(PYTHON_VERSION_CODE))
PYTHON_SCRIPT_RESULTS := $(shell python test.py)
.PHONY: all
all:
@echo $(PYTHON_SCRIPT_RESULTS)
Embed Python in Makefile to set make variables
You have to quote the string you pass to Python:
SDK_PATH ?= $(shell python -c '$(DETECT_SDK)')
Otherwise the shell will be confused trying to parse the Python script.
EDIT:
I don't understand your Python script though. Either your indentation is wrong, so the else
is supposed to be attached to the if (grrr...) or else you're missing a break
statement... or possibly the else
is just useless. As it's written, it will generate a newline-separated list of paths that exist, plus ".". If you describe what you're really trying to do, rather than just say you gave up, we can help.
For example, if what you want to do is print the first existing path in that list or "." if none exist (that is, your Python loop is missing a break
after the print
), then you can easily do this in GNU make:
SDK_PATH_LIST = ../google/appengine /usr/local/google_appengine ../.locally/google_appengine
SDK_PATH ?= $(firstword $(wildcard $(SDK_PATH_LIST:%=%/.)) .)
Makefile as an executable script with shebang?
#!/usr/bin/make -f
main:
@echo Hello World!
Is normally all you need in a standard make file. The filename is implicitly passed as the last argument. /dev/stdin
here is (usually) the tty. You can do the whole env
thing if there's a reason to, but often there's no need.
ajw@rapunzel:~/code/videocc/tools > vi Makefile
ajw@rapunzel:~/code/videocc/tools > chmod a+x Makefile
ajw@rapunzel:~/code/videocc/tools > ./Makefile
Hello World!
how to have command as input for a shell launched inside a python subprocess
Using the subprocess
module, it could be achieved this way. You can use the stdin stream to write your command to execute once the actual environment has been set.
start_workspace.perl
print "Perl: Setting some env variables\n";
$ENV{"SOME_VAR"} = "some value";
print "Perl: Starting bash\n";
exec('bash');
In python:
import subprocess
p = subprocess.Popen( "perl start_workspace.perl", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
p.stdin.write('echo "Python: $SOME_VAR"\n')
p.stdin.write("make\n")
(stdoutdata, stderrdata) = p.communicate()
print stdoutdata
print stderrdata
Output is
Perl: Setting some env variables
Perl: Starting bash
Python: some value
make: *** No targets specified and no makefile found. Stop.
Piping stdout and stderr inside a Makefile rule
It doesn't explain why the straightforward approaches don't work, but it does the trick:
[Makefile]
test:
python test.py >test.out 2>&1; pyrg <test.out
How to get the exit status and the output of a $(shell command) before make 4.2?
I just can't understand why you're trying to make use of $(shell ...)
at all. This is so overly complex, and so meaningless. The only effect of $(shell ...)
is that it expands before any recipe is run. But you never try to make use of that. On the contrary, it looks only natural to move the script directly inside the recipe.
For example, consider this:
unused = """
ifeq (true,false)
"""
# some python stuff
print("Hello world")
exit(1)
unused = """
endif
# here comes make stuff
.ONESHELL:
.PHONY: all
all:
@/usr/bin/python $(lastword $(MAKEFILE_LIST))
ec=$$?
echo "script exitcode is $$ec"
exit $$ec
#"""
Maybe even better solution is simply to make python
a custom SHELL
for a single rule. Although, in this case it could be tricky to mix python and shell scripts in the same rule (but I don't think it's really essential).
How can pass the value of a variable to the standard input of a command?
Simple, but error-prone: using echo
Something as simple as this will do the trick:
echo "$blah" | my_cmd
Do note that this may not work correctly if $blah
contains -n
, -e
, -E
etc; or if it contains backslashes (bash's copy of echo
preserves literal backslashes in absence of -e
by default, but will treat them as escape sequences and replace them with corresponding characters even without -e
if optional XSI extensions are enabled).
More sophisticated approach: using printf
printf '%s\n' "$blah" | my_cmd
This does not have the disadvantages listed above: all possible C strings (strings not containing NULs) are printed unchanged.
How to pass argument to Makefile from command line?
You probably shouldn't do this; you're breaking the basic pattern of how Make works. But here it is:
action:
@echo action $(filter-out $@,$(MAKECMDGOALS))
%: # thanks to chakrit
@: # thanks to William Pursell
EDIT:
To explain the first command,
$(MAKECMDGOALS)
is the list of "targets" spelled out on the command line, e.g. "action value1 value2".
$@
is an automatic variable for the name of the target of the rule, in this case "action".
filter-out
is a function that removes some elements from a list. So $(filter-out bar, foo bar baz)
returns foo baz
(it can be more subtle, but we don't need subtlety here).
Put these together and $(filter-out $@,$(MAKECMDGOALS))
returns the list of targets specified on the command line other than "action", which might be "value1 value2".
Related Topics
What Is the Naming Convention in Python For Variable and Function
How to Load All Modules in a Folder
How to Base-64 Encode a Png Image for Use in a Data-Uri in a CSS File
CSS Problems with Flask Web App
Google App Engine: Won't Serve Static Assets with Below Error:
How to Split a Huge CSV File Based on Content of First Column
Cron Job: How to Run a Script That Requires to Open Display
Fetching the Output of a Command Executed Through Os.System() Command
Pipe Raw Opencv Images to Ffmpeg
Get Local Network Interface Addresses Using Only Proc
How to Run Multiple Subprocesses via Fork()
How to Find Out the Date of the Last Saturday in Linux Shell Script or Python
Trouble Connecting to Phantomjs Webdriver Using Python and Selenium
Python Multiprocessing Pool.Apply_Async with Shared Variables (Value)