36

I have a version.c file in my project that contains current revision of the project and some other stuff that is passed as a definition (-D compiler option) from makefile.

I know that to force make to compile version.c always regardless of modification date I can touch version.c.

Is there a makefile only way to achieve this? If I write .PHONY : version.o the object file doesn't get build at all.

EDIT: Here is my makefile:

export CC = gcc


export MODULES = $(sort \
     sys \
     cim \
     version \
)

export FILES = $(sort \
             main.c \
             cim.c \
             version.c \
)

VPATH = $(MODULES)

OBJS = $(FILES:.c=.o)

INCLUDES = $(addprefix -I,$(MODULES))

all:$(OBJS)
    $(CC) $(INCLUDES) $(OBJS) -o main.exe


clean:
    rm -rf *.o *.exe

cim.o: cim.c
main.o: main.c cim.o
version.o: version.c

.PHONY: version.o

.c.o :
    $(CC) $(CFLAGS) $(INCLUDES) -c $<
devemouse
  • 5,302
  • 5
  • 22
  • 22
  • Is the missing `:` after `.PHONY` a copy/paste error in your post? Could you show a bit of your Makefile? Also: http://stackoverflow.com/questions/816370/how-do-you-force-a-makefile-to-rebuild-a-target – Mat Oct 04 '11 at 06:08
  • Please show at least part of your Makefile. The `.PHONY` "trick" works. – Mat Oct 04 '11 at 06:13
  • The targets 'all' and 'clean' are legitimately phony targets. I remain to be convinced that 'version.o' can legitimately be classified as a phony target. After all, it is a real file. – Jonathan Leffler Oct 04 '11 at 06:29
  • but this is what i get in result: gcc -Icim -Isys -Iversion -c cim/cim.c gcc -Icim -Isys -Iversion -c sys/main.c gcc -Icim -Isys -Iversion cim.o main.o version.o -o main.exe gcc.exe: version.o: No such file or directory make[1]: *** [all] Error 1 – devemouse Oct 04 '11 at 06:33

4 Answers4

59

The classic way to do it is:

version.o:   .FORCE

.FORCE:

(and you might add .PHONY: .FORCE). The file '.FORCE' is presumed not to exist, so it is always 'created', so version.o is always out of date w.r.t it, so version.o is always compiled.

I'm not sure that making version.o into a phony file is correct; it is actually a real file, not a phony one.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
32

Not a makefile way, but easier than touch:

make -B

‘-B’ ‘--always-make’

Consider all targets out-of-date. GNU make proceeds to consider targets and their prerequisites using the normal algorithms; however, all targets so considered are always remade regardless of the status of their prerequisites. To avoid infinite recursion, if MAKE_RESTARTS (see Other Special Variables) is set to a number greater than 0 this option is disabled when considering whether to remake makefiles (see How Makefiles Are Remade).

tartaruga_casco_mole
  • 1,086
  • 3
  • 21
  • 29
12

If you want to do this using the FORCE mechanism the correct solution looks like this:

version.o: FORCE

.PHONY: FORCE
FORCE:

By explicitly declaring FORCE to be phony we make sure things will work right even if .SECONDARY: is used (.SECONDARY: will cause FORCE to be considered an intermediate file, and make doesn't rebuilt intermediate files unless they have prerequisites newer than the ultimate target, and FORCE doesn't have any prerequisites, so .PHONY: FORCE is needed).

The other solution (using $(shell touch version.c)) also has a problem: it may cause your editor to think version.c has been updated, and prompt for a reload of the file, which might end up being destructive if you've been editing the file's buffer but haven't yet saved it. If you don't mind this, it can be made even simpler by observing that the touch command is silent, so the assignment to the hack dummy variable isn't needed:

$(shell touch version.c)  # This is enough, but will likely confuse your editor

The .PHONY "trick" referred to in the comments on the question generally DOES NOT work. It may look like it does because it will force a relink iff version.o already exists, but the actual object file won't get rebuilt if the .o file rule is an implicit rule (which it usually is). The problem is that make doesn't do the implicit rule search for explicitly phony targets. This make file shows the failure:

fooprog: test.o
        cp $< $@

%.o: %.c
        cp $< $@

.PHONY: test.o # WRONG

clean:
        rm test.o fooprog

If a static pattern rule is used instead of an implicit rule the .PHONY: version.o trick will work. In general using static pattern rules instead of implicit rules cuts out most of the more confusing Make behaviors. But most make files use implicit rules.

Britton Kerin
  • 427
  • 4
  • 9
2

The quick hack version when you just need it to work and you don't want to play Make games:

# Hack to get main.c rebuilt
hack := $(shell touch main.c)

Basically just make Make run touch for you.

Brad
  • 5,845
  • 7
  • 30
  • 29