如何转义Makefile中的空格

时间:2015-06-06 21:39:16

标签: makefile escaping

假设我想将位于/home/me/Google Drive/Foobar/的C ++项目编译成名为Foobar的可执行文件,我想使用GNU Make来自动完成该过程。

这是我的Makefile的样子:

OUTPUT = $(notdir $(CURDIR))

all $(OUTPUT):
    g++ *.cpp -o $(OUTPUT)

问题是,由于项目路径中有空格,notdir命令正在解释两个单独的路径并返回Google Foobar

我尝试在$(CURDIR)$(notdir "$(CURDIR)"))周围加上引号,但我收到以下错误:

/bin/sh: -c: line 0: unexpected EOF while looking for matching `"'
/bin/sh: -c: line 1: syntax error: unexpected end of file
Makefile:4: recipe for target 'all' failed
make: *** [all] Error 1

我不明白问题的来源。

另外,我希望得到一个不涉及更改路径名称的答案...谢谢:)

4 个答案:

答案 0 :(得分:1)

您可以尝试使用space中的_替换$(CURDIR),然后获取$(OUTPUT)。如下所示

null      :=
SPACE     := $(null) $(null)
OUTPUT     = $(notdir $(subst $(SPACE),_,$(CURDIR)))

all $(OUTPUT):
    g++ *.cpp -o $(OUTPUT)

基本上在 string substitution (subst)

之后
$(OUTPUT) will be Foobar

答案 1 :(得分:0)

存储目录时GNU make端的问题少于shell扩展端的问题。所以改变

 g++ *.cpp -o $(OUTPUT)

为:

 g++ *.cpp -o "$(OUTPUT)"

使用名为remake的GNU make变体,您可能更容易看到它。

使用重制,如果您想验证$ OUTPUT的值是否有空格,您可以运行:

$ remake -X
GNU Make 4.1+dbg0.91
...
-> (/home/me/Google Drive/Makefile:3)
all: 
remake<0> expand OUTPUT
Makefile:1 (origin: makefile) OUTPUT := Google Drive

现在,如果您想查看执行与GNU make相同的操作的shell脚本,请使用 write 命令:

remake<1> write all
File "/tmp/all.sh" written.

以上所有 make 目标名称。然后查看/tmp/all.sh这只是一个shell脚本,你会发现那里有问题,当然可以通过添加引号来修复。

答案 2 :(得分:0)

看起来这种组合在这种情况下起作用。

import argparse
import collections
import csv
import simplejson as json


def read_and_write_file(json_file_path, csv_file_path, column_names):
    """Read in the json dataset file and write it out to a csv file,given the column names."""
    with open(csv_file_path, 'wb+') as fout:
    csv_file = csv.writer(fout)
    csv_file.writerow(list(column_names))
    with open(json_file_path) as fin:
        for line in fin:
            line_contents = json.loads(line)
            csv_file.writerow(get_row(line_contents, column_names))

 def get_superset_of_column_names_from_file(json_file_path):
"""Read in the json dataset file and return the superset of column  names."""
column_names = set()
with open(json_file_path) as fin:
    for line in fin:
        line_contents = json.loads(line)
        column_names.update(
                set(get_column_names(line_contents).keys())
                )
return column_names

 def get_column_names(line_contents, parent_key=''):
"""Return a list of flattened key names given a dict.
Example:
    line_contents = {
        'a': {
            'b': 2,
            'c': 3,
            },
    }
    will return: ['a.b', 'a.c']
These will be the column names for the eventual csv file.
"""
column_names = []
for k, v in line_contents.iteritems():
    column_name = "{0}.{1}".format(parent_key, k) if parent_key else k
    if isinstance(v, collections.MutableMapping):
        column_names.extend(
                get_column_names(v, column_name).items()
                )
    else:
        column_names.append((column_name, v))
return dict(column_names)

def get_nested_value(d, key):
"""Return a dictionary item given a dictionary `d` and a flattened key from `get_column_names`.

Example:
    d = {
        'a': {
            'b': 2,
            'c': 3,
            },
    }
    key = 'a.b'
    will return: 2

"""
if '.' not in key:
    if key not in d:
        return None
    return d[key]
base_key, sub_key = key.split('.', 1)
if base_key not in d:
    return None
sub_dict = d[base_key]
return get_nested_value(sub_dict, sub_key)

def get_row(line_contents, column_names):
"""Return a csv compatible row given column names and a dict."""
row = []
for column_name in column_names:
    line_value = get_nested_value(
                    line_contents,
                    column_name,
                    )
    if isinstance(line_value, unicode):
        row.append('{0}'.format(line_value.encode('utf-8')))
    elif line_value is not None:
        row.append('{0}'.format(line_value))
    else:
        row.append('')
return row

if __name__ == '__main__':
"""Convert a yelp dataset file from json to csv."""

parser = argparse.ArgumentParser(
        description='Convert Yelp Dataset Challenge data from JSON format to CSV.',
        )

parser.add_argument(
        'json_file',
        type=str,
        help='The json file to convert.',
        )

args = parser.parse_args()

json_file = args.json_file
csv_file = '{0}.csv'.format(json_file.split('.json')[0])

column_names = get_superset_of_column_names_from_file(json_file)
read_and_write_file(json_file, csv_file, column_names)

答案 3 :(得分:0)

执行:

OUTPUT = $(notdir $(lastword $(CURDIR)))

all $(OUTPUT):
    g++ *.cpp -o $(OUTPUT)