Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Does make have any sort of way to see if a .h file changed, that all C/C++ source files that directly or indirectly include it need to be recompiled, but others don't need to?


Make does not do this directly. Typically you generate a set of dependencies using gcc. gcc can be told to output a rule suitable for use in make that describes the dependencies of a source file. See the -M option and friends.


Not make by itself, but gcc comes with related preprocessor options[1], in particular -MMD.

Add that to your CFLAGS and include the generated dependency files by adding something like

    -include $(OBJECTS:%.o=%.d)
to the Makefile.

[1] http://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html


Another commenter already pointed out the `-M` flag on GCC (and Clang), but I thought I'd share the rule I use to provide automatic dependencies. It's a bit simpler than the one suggested in the GNU Make Manual:

https://github.com/mcinglis/c-style#use-gccs-and-clangs--m-t...


I suggest just building with "-MMD -MP", using "-MT" if for some reason you want .d files to reside elsewhere. The "-MP" option prevents build errors when a file is removed. No need for crazy redirects or an actual rule to create the .d files.


`-MP` makes sense, but I don't see how Make could work out when to regenerate the dependency files themselves without the `-MT` value as in my rule, or the `sed` expression given in the GNU Make Manual. Maybe I'm missing something about `-MMD` - I don't understand everything said about it in the manpage of GCC.

Generally it's my style to prefer I/O redirection in the shell to programs taking output parameters and managing their own files. Thus, using `> $@` rather than `-MF` or `-MD`.


You seem to be invoking the compiler separately for the sole purpose of building .d files (with a %.d: %.c rule). Don't do it that way. With the -MMD option, you create the .d file as a side-effect of the real compilation. Any change that would require the .d file to be rebuilt has to involve a change to the old dependencies as listed in the old .d file. So the source file will be recompiled. In order for a new dependency on a new header file to be added, an existing and remaining dependency needs to change to add '#include ...'. So the .c file will get recompiled because that file has changed and then you have a new .d file.

For C/C++, I have to subvert GNU make's attempts to rebuild .d files by using $(wildcard) on them and inserting a /./ in the middle of the path.

Note that there are other cases where I do have a rule for building .d files and have them rebuilt. In particular for Fortran 90 modules. This occurs wherever you need to build the .d files first for the initial first build to be in the correct order. This is only an issue for C/C++ if you are invoking a program to generate C sources (e.g. rpcgen). In practice, that is often best handled with a few dependencies listed explicitly in your Makefile.


Yes, but you have to work a little bit for it.

If your rule that builds .o files from .c/.cpp files uses the one of the dependency-generating flags to GCC (options beginning with -M), GCC will create an alternate or additional (depending on the flag) make-compatible file that describes what files were included during the build. If you then include these files in your Makefile with the 'include' directive, then you'll get the behavior you're looking for.

Implementing it correctly can be a little tricky, but once you understand how to do it it's not too bad. As I recall there used to be some subtle issues that required some post-processing of the GCC-generated dependency files to avoid a problem when header files were renamed or removed (foo.c included foo.h, so a dependency was generated; later foo.c was modified to not require foo.h, and foo.h was removed, but the build still thinks it's required to build) -- it looks like GCC now has a -MP option to add phony empty rules for all dependencies, allowing make to power through these.


Make only understands rules such as "X depends on Y", but gcc can output these dependency rules (-M* switches). So yes, it is possible to do this but make itself is source code agnostic.


Depends on which version of "make" you're using. GNU make does not, but automatic dependency detection is just one of many enhancements in Electric Make, a drop-in replacement for GNU make.


For this reason and others I just wrote my own build script using /bin/sh:

https://github.com/chkoreff/Fexl/blob/master/build

Configurable with a small src/config file:

https://github.com/chkoreff/Fexl/blob/master/src/config

It automatically greps header dependencies, caching them in obj/*.i files.


GCC already does this for you (with the -M... options that others have mentioned). Don't re-invent the wheel.

.i is the extension for pre-processed C source. If you re-use it for something else build-related, I guarantee you'll regret it.


Thanks. I'm not using make, so I don't really need a make rule, but I can see that gcc -M does something useful:

  $ gcc -M src/value.c
  value.o: src/value.c src/memory.h src/value.h
The result of my grep/sed gives me just the header dependencies alone, which is really all I need:

  $ cat obj/value.i
  src/memory.h src/value.h
So I might consider replacing the grep/sed with gcc -M, and strip off the first two entries, which would give me the equivalent result, but it doesn't strike me as a "must do" right now. Again, I don't use make, just /bin/sh, so I don't need a make rule per se.

Thanks for the advice about the ".i" suffix. I don't think there's a conflict though, because all my intermediate files go into a completely separate "obj" directory, and no pre-processed source will be going there. However, I will consider choosing a different suffix just for the heck of it. I'm sure anything I choose (such as ".dep" or ".inc") will mean something to somebody somewhere, but since I'm in the entirely orthogonal context of the "obj" directory I don't think it matters.


Everbody seems to use .dep, FWIW.



I know you already have quite a few answers to this, but you could also use makedepend.




Consider applying for YC's Winter 2027 batch! Applications are open till November 2.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: