How to get pattern rules to match file names with

2019-04-08 08:04发布

问题:

In the GNU make docs, '%' is documented to match "any nonempty substring". However, it seems it actually only matches non-empty substrings that do not contain whitespace. For example, say you do this:

mkdir /tmp/foo
cd /tmp/foo
echo 'int main() { return 0; }' > "test.c"
echo 'int main() { return 0; }' > "test space.c"

Now, you should be able to build these using GNU Make's built-in pattern rules:

anthony@Zia:/tmp/foo$ make "test"
cc     test.c   -o test
anthony@Zia:/tmp/foo$ make "test space"
make: *** No rule to make target `test space'.  Stop.

The same problem happens when you write a makefile.

anthony@Zia:/tmp/foo$ rm test
anthony@Zia:/tmp/foo$ echo 'all: test test\ space' > Makefile 
anthony@Zia:/tmp/foo$ make
cc     test.c   -o test
make: *** No rule to make target `test space', needed by `all'.  Stop.

Even if you explicitly add in a %: %.c rule, the result is the same. But if you add in an explicit rule to the Makefile, like this, it works:

test\ space: test\ space.c
    $(CC) -o "$@" "$<"     # first char is tab, of course.

Is there a trick to get spaces to work with implicit rules?

edit

I've sent a bug report: http://lists.gnu.org/archive/html/bug-make/2011-06/msg00002.html

回答1:

I don't believe so. The notion of a list of whitespace-separated tokens being passed around as a string is pretty deeply ingrained in make. Those lists are parsed and reparsed. There's a reason why spaces in directory and file names is considered bad practice in the UNIX world.



回答2:

This is a kludge, but as of today, people still get given paths with spaces in sometimes.

Anyway, making a link instead of directly accessing the directory in the % rule works OK.

# GNU makefile
DIR_WITH_SPACE=/c/Users/me/My\ Code

# *** DOESN'T WORK ***
%.h : $(DIR_WITH_SPACE)/%.h
    cp -v "$<" "$@"

fix:
  ln -s $(DIR_WITH_SPACES) dir_fixed

# Does work :)
%.h : dir_fixed/%.h
    cp -v "$<" "$@"