grorel
grorel

Reputation: 1466

patsubst's returned value when no pattern found

I'm trying to send "sub-make" commands to a subdirectory. I have a Parent Directory with a "top_level" Makefile and a child directory with its own Makefile.

My parent Makefile has a target line as follow :

target%:
    make -C sub_dir $(patsubst target-%,%,$@)

I can do in the parent folder:

make target-clean && make target-all

It will be interpreted as :

make -C sub_dir clean && make -C sub_dir all

I want to be able to do:

make target

but in this case, I get :

make -C sub_dir target.o

I was expecting that while "patsubst" does not find the pattern, it will return either nothing or the tested expression. But it returns this "target.o".

Can someone explain it to me ? How can I manage to get nothing ?

I tried these expressions without success:

make -C sub_dir $(patsubst target%,%,$@)
make -C sub_dir $(patsubst -%,%,$(patsubst target%,%,$@))
make -C sub_dir $($(patsubst -%,%,$(patsubst target%,%,$@)):.o=)

The last one is tricky, it gives:

make -C sub_dir
make[1]: Entering directory /home/aurelien/Documents/Projects/parent/sub_dir'
make[1]: 'subtarget' is up to date.
make[1]: Leaving directory '/home/aurelien/Documents/Projects/parent/sub_dir'
cc target.o -o target
cc: target.o: No such file or directory
cc: no input files
make: *** [target] Error 1

Upvotes: 0

Views: 194

Answers (2)

MadScientist
MadScientist

Reputation: 100876

The problem is that a pattern must match one or more characters. So, this pattern:

target%:

does not match the target name target, because there are no characters left over to match the pattern.

So, make looks for another implicit rule that can be used to build target and it finds the built-in rule:

% : %.o

so it tries to build target.o. This target will match the pattern target% with a stem of .o, so it tries to use your rule to build that.

To specifically answer your question, any word that does not match the substitution pattern in patsubst will be passed through without changing it.

Upvotes: 0

Renaud Pacalet
Renaud Pacalet

Reputation: 29230

The target% pattern matches but only with at least one character for the %, not zero. From the GNU make manual:

A pattern rule contains the character ‘%’ (exactly one of them) in the target; otherwise, it looks exactly like an ordinary rule. The target is a pattern for matching file names; the ‘%’ matches any nonempty substring, while other characters match only themselves.

So target does not match and make uses its implicit rules to build target: build target.o and then target from target.o. When trying to find a way to build target.o, the pattern rule matches and the recipe:

make -C sub_dir $(patsubst target-%,%,$@)

is expanded. But as target.o does not match target-%, patsubst does nothing and your recipe becomes:

make -C sub_dir target.o

Upvotes: 1

Related Questions