4 ms·
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
by Aardwolf 13y ago
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?
- lrm242 13y agoMake 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.
- emillon 13y agoMake 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.
- cygx 13y agoNot 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 http://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html
- deleted 13y ago[deleted]
- deleted 13y ago[deleted]
- itp 13y agoYes, 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.
- blueblob 13y agoI know you already have quite a few answers to this, but you could also use makedepend.
- fexl 13y agoFor this reason and others I just wrote my own build script using /bin/sh: https://github.com/chkoreff/Fexl/blob/master/build https://github.com/chkoreff/Fexl/blob/master/build Configurable with a small src/config file: https://github.com/chkoreff/Fexl/blob/master/src/config https://github.com/chkoreff/Fexl/blob/master/src/config It automatically greps header dependencies, caching them in obj/*.i files.
- alextingle 13y agoGCC 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.
- fexl 13y agoThanks. 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.
- alextingle 13y agoEverbody seems to use .dep, FWIW.
- 13y ago
- majika 13y agoAnother 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-to-automatically-generate-object-file-dependencies https://github.com/mcinglis/c-style#use-gccs-and-clangs--m-t...
- jedbrown 13y agoI 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.
- majika 13y ago`-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`.
- opk 13y agoYou 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.
- emelski 13y agoDepends 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.