Files available:

src1.c
src1. h
src2.c
src3.c
src4.c
src4. h

It is worth paying attention that NOT for all .c files there are own .h files.

The current makefile works, but with the proviso: when changing any .h file, ALL .c files are rebuilt:

SRCS = $(wildcard *.c) HDRS = $(wildcard *.h) %.o: %.c $(HDRS) @$(CC) -c -o $@ $< 

If you expand the contents of the $ (HDRS) variable, the automatic build will look like this:

 %.o: %.c src1.h src4.h @$(CC) -c -o $@ $< 

That is why if only one src4.h file is changed, then all * .c files will be re-assembled.

In another case, an attempt to do so as indicated in the example below will lead to an error, because the src2.h files src3.h do not exist:

 %.o: %.c %.h @$(CC) -c -o $@ $< 

Be kind, tell me, please, how to make the right Makefile so that when src4.h changes, only src4.c is reassembled, but not the rest.

All my independent attempts to find the answer to this question were unsuccessful.

Thank you in advance for your advice.

  • one
    Well, the simplest is to write the dependencies explicitly. Like this: src1.o: src1.c src1.h and so on ... Only four lines - is it worth inventing something ?! :-) - Sergey
  • @Sergey, in fact, under a hundred files, the project is developing dynamically, so only the automatic version is interested in the poet. - Dennis VR
  • one
    The first thing that comes to mind is to use cmake - it determines the dependent headers. - Sergey
  • one
    @ DennisV.R .: I don’t remember offhand, but here it seems to be there: en.wikipedia.org/wiki/Makedepend - VladD
  • one
    SMake is another monster file for cmake, after a file for make, like Russian after Chinese ... :-) Maybe cmake and a monster, which is understandable, almost without preparation. but make, the more you read about it, the more you get confused :-) - Sergey

3 answers 3

You can specify dependencies manually in the Makefile

 src1.o: src1.c src1.h 

and so far for all obeknikov

Or create dependency files * .d for all * .c files and include them in the Makefile

 SRCS = $(wildcard *.c) HDRS = $(wildcard *.h) OBJ_CATALOG=.obj/ OBJS=$(patsubst %.c,$(OBJ_CATALOG)%.o,$(SRCS)) DEPEND_CATALOG=.depend/ DEPEND=$(patsubst %.c,$(DEPEND_CATALOG)%.d,$(SRCS)) $(OBJ_CATALOG)%.o:%.c $(CXX) $(CFLAGS) -c $< -o $@ $(DEPEND_CATALOG)%.d:%.c $(CXX) -MM -I. $< | sed -e '1s/^/.obj\//' > $@ include $(DEPEND) 
  • Maybe someone will benefit from a very good article with examples. Thanks @Yaroslav, found thanks to the "-MM" parameter: Autodependencies with GNU make - Dennis VR

will lead to an error

will not lead if there are two rules. one with two prerequisites, the second with one.


example. for simplicity, it is not the compiler that is called, but the touch program:

 $ cat GNUmakefile %.o: %.c %.h @echo 'обновился(ись) $?, делаю:' touch $@ %.o: %.c @echo 'обновился $?, делаю:' touch $@ 

create only the файл.c :

 $ touch файл.c $ make файл.o обновился файл.c, делаю: touch файл.o 

now add the файл.h :

 $ touch файл.h $ make файл.o обновился(ись) файл.h, делаю: touch файл.o 

note that the first rule (with two prerequisites) worked. if we rearrange the rules in places (the first will go with one prerequisite rule, and the second with two), then the rule with two prerequisites “will not work” - gnu / make will find the first suitable rule and will “calm down” on this.

update both files - файл.c and файл.h :

 $ touch файл.c файл.h $ make файл.o обновился(ись) файл.c файл.h, делаю: touch файл.o 

Well, finally, if no source file has been updated, then:

 $ make файл.o make: «файл.o» не требует обновления. 
  • Great option! However, the example given by @Yaroslav is more universal. It works even if the file name .c and .h do not match. It is enough to use #include one in the other. - Dennis VR

A bit late, but why not a simple patsubst :

 SRCS = $(wildcard *.c) HDRS = $(wildcard *.h) SRCS_W_HDRS := $(patsubst %.h, %.c, $(HDRS)) $(SRCS_W_HRDS): %.c: %.h 
  • Better later than never) Thanks for the interesting option! - Dennis VR