Chance Chance - 1 year ago 53
C++ Question

In a makefile, is a directory name a phony target or "real" target?

According to what I have read about makefiles, a phony target is any target that does not correspond to an actual filename. My intuition says that a directory as a target would be treated the same as a file.

Why is this important? I have a directory as a target in my makefile. when I have it as a prerequisite to my primary executable, that executable always gets made, whether or not everything is up to date. If I take it out as a prerequisite, my makefile is smart enough to know when things need to be built, but I have the problem of not knowing if the directory needs to be created. According to what I have read about make, any phony targets are not good as prerequisites because make does not know if they are up to date, so they will always rebuild the associated target. Here is an excerpt from my makefile.

@echo "--------------------------------------------";
@echo "$(THIS_DIR) $(MACHINE)";
@echo "Linking Shared Library";
@echo "ar -rc $(EXEC_WITH_PATH) INSERT::{OBJS}";
ar -rc $(EXEC_WITH_PATH) $(OBJS);
@echo "--------------------------------------------";

# Make dirs for object code and links
${OBJ_DIR} :
@if [ ! -d ${OBJ_DIR} ]; then \
mkdir ${OBJ_DIR}; \

So in this case, is
, a directory name, a phony target or not?

Answer Source

Edit: This only applies to GNU make - a fair assumption given the "linux" tag.

Your target is a real target, not a PHONY one. The problem is that the output directory gets updated when you put targets in it so that it is always newer than your target. This means your target will always get built because it is out of date with respect to its dependencies.

What you need is an order-only prerequisite. These prerequisites allow you to specify that it needs to be built if it does not exist, but not to pay attention to the timestamp. That is, a target will not be out of date with respect to order-only prerequisites.

You specify it like this:


Anything after the vertical bar is an order-only prerequisite.

You can now make your OBJ_DIR target simpler:

${OBJ_DIR} :
        mkdir -p ${OBJ_DIR}

Note: I've used the ${OBJ_DIR} syntax instead of $(OBJ_DIR) because that is what you used. Order-only prerequisites do not depend on that syntax.