Allow space in target of GCC makefile

2019-02-21 22:30发布

Is there a way to get spaces inside target names working when using make.exe? It seems to be impossible if this really ancient bug report is correct: http://savannah.gnu.org/bugs/?712

For reference, the big problem is that pieces of makefile commands like:

"foo bar baz": $(OBJ)
    $(CPP) $(LINKOBJ) -o $(BIN) $(LIBS)

... seem to get treated as three separate commands: one to build "foo (note the included "), one to build bar, and lastly, one to build baz" (again, including "). This is because make.exe seems to be using space as a delimiter.

However, it's reasonable to assume that one might want to build "Hello World.exe" for example. This doesn't seem to be possible. Double quotes don't work, and neither does escaping the separate words (I've read that somewhere, don't remember the link):

"foo\\ bar\\ baz": $(OBJ)
    $(CPP) $(LINKOBJ) -o $(BIN) $(LIBS)

Is there any other way to fix this? The official manual only confirms the tokenize-by-spaces stuff, but doesn't provide a way to use space for any other purpose: http://www.gnu.org/software/make/manual/make.html#Rule-Syntax

Edit: as suggested, I've tried single slashes too, but these have the exact same effect as double slashes. Make complains it can't find rules for the first word:

mingw32-make.exe: *** No rule to make target `foo', needed by `all'.  Stop.

The executable "foo bar baz.exe" is correctly produced though, but linking is done each time per word.

3条回答
地球回转人心会变
2楼-- · 2019-02-21 22:46

Maybe easier to consider a simpler Makefile, which ignores the dependencies in the standard targetRule: dependencies invocation. The OP is for Windows, and the below is done on Linux in the bash shell; but it should probably be applicable to Windows using the bash shell via cygwin, I guess. I have the following in my Makefile (note, there should be a TAB before the echo commands, which SO converts to spaces):

testA:
    echo "testA"

unrelated:
    echo "unrelated"

testA\ clean:
    echo "testA clean"

clean:
    echo "clean"

If I call make with targets clean or testA in the bash shell terminal, I get the expected results:

$ make testA 
echo "testA"
testA
$ make clean
echo "clean"
clean

Now, if I call make testA clean just written as is, the bash shell will split the arguments at spaces, so make will receive two arguments, and will run them separately:

$ make testA clean
echo "testA"
testA
echo "clean"
clean

... but if I wrap the target supplied to make in quotes - or if I escape the space - the shell will understand that it is supposed to be a single argument with a space inside, and will propagate it as such to make, which will proceed to execute what is written as the testA\ clean target rule:

$ make "testA clean"
echo "testA clean"
testA clean
$ make testA\ clean
echo "testA clean"
testA clean

One consequence of this, is that unfortunately you cannot "TAB" at the command line for autocompletion of testA\ clean; if you type make teTAB at the command line, only testA will be autocompleted automatically (and the testA\ clean will not be shown as an autocomplete option).

查看更多
\"骚年 ilove
3楼-- · 2019-02-21 22:51

Instead of double backslash use single ones. The following Makefile works (at least for gnu make):

goal:   foo\ bar

foo\ bar:
    gcc -o "foo bar" "foo bar.c"
查看更多
男人必须洒脱
4楼-- · 2019-02-21 23:05

as Matthias said, it's a matter of "\ ", but of double quote too. Here is how I succeded into this :

EXECUTABLE=foo\ bar\ baz
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
                $(CC) $(OBJECTS) -o "$@" $(LDFLAGS)

Note the double quotes around the $@ It seems to me that when make reach the target "$(EXECUTABLE)" it expands the "\ ", so the command line becomes

gcc file.o -o foo bar baz -LFlags

which is not what you want, you want double quotes around the name of the file.

Now you are on windows and I don't remember how it deals with spaces in names, so as Matthias said, first check how "cmd.exe" deals with spaces (except by surrounding name with double quotes...)

查看更多
登录 后发表回答