makefile

Difference between % and * in makefile


What is the difference between these 2 statements?

I ran both. % gives names with replaced with .o but * doesn't change anything, just gives same cc files. I was told both are same but apparently not.

When to use what?

CXX_OBJECTS = $(patsubst $(SOURCE_DIR)/%.cc, $(BUILD_DIR)/%.o, $(CXX_SOURCES))
CXX_OBJECTS = $(patsubst $(SOURCE_DIR)/*.cc, $(BUILD_DIR)/*.o, $(CXX_SOURCES))

Solution

  • GNU make uses glob-style patterns in a few places. You can use them where names of targets or prerequisites are expected, or when calling the builtin $(wildcard) function. The basic glob wildcard operators are *, ?, and [...]. These allow you to specify a pattern that match zero or more actual, existing filenames.

    However, when GNU make needs to transform one filename into another (e.g., to discover that the source file for "foo.o" is "foo.c"), it uses "%", which is its own internal wildcard character that, like a glob "*", matches zero or more characters.

    $(patsubst) operates on text. GNU make has no inclination to treat any of its arguments as file wildcards that it should check the filesystem for. It expects to find a % pattern and a % replacement. It's easy to be confused because "*" and "%" mean the same thing in terms of patterns: match zero or more characters.

    A way to remember it is that glob-style patterns (*/?/[]) imply making a list of actual filenames that match those patterns, that is, actually checking the filesystem to find matches. %, on the other hand, implies no checking with the filesystem at all, and also implies you're likely going to be using the fragment that matched the % in some replacement text (such as via an implicit rule).