2

I have a complex logic for detecting path for Makefile variable. I gave up on doing this in make language, so I coded it in Python, and want to embed the code into Makefile to set variable. However, this doesn't work:

define DETECT_SDK
import os
locations = [
  "../google_appengine",
  "/usr/local/google_appengine",
  "../.locally/google_appengine",
]
for path in locations:
  if os.path.exists(path):
    print(path)
    break
else:
  print(".")
endef

SDK_PATH ?= $(shell python -c $(DETECT_SDK))

default:
        python -c 'import sys; print(sys.argv)' $(SDK_PATH)

UPDATE: Updated multiline definition from Is it possible to create a multi-line string variable in a Makefile Previously it was failing with Makefile:2: *** missing separator. Stop.. Now it fails with another error:

/bin/sh: 1: Syntax error: "(" unexpected
python -c 'import sys; print(sys.argv)' 
['-c']
4

2 回答 2

2

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:%=%/.)) .)
于 2013-06-15T18:25:15.600 回答
1

由于一些make试图执行多行字符串的错误,以下对我有用:

define NEWLINE


endef

define DETECT_SDK
import os
locations = [
  "../google_appengine",
  "/usr/local/google_appengine",
  "../.locally/google_appengine",
]
for path in locations:
  if os.path.exists(path):
    print(path)
    break
endef

SDK_PATH ?= $(shell echo '$(subst $(NEWLINE),@NEWLINE@,${DETECT_SDK})' | sed 's/@NEWLINE@/\n/g' | python -)

default:
        @echo 'SDK Path Detected: $(SDK_PATH)'
于 2013-06-17T15:35:34.683 回答