3

As I was debugging and optimizing one of my C/C++-projects, I often disabled and enables the profiling flags -p -g -pg and some optimization flags in my Makefile to have a better look at whats happening.

However, GNU make did not detect this change and did not do a recompile.

How to properly rebuild a whole software project with some new flags (or some removed) without manually doing a make clean?

stefan
  • 10,215
  • 4
  • 49
  • 90
  • As you might see, I already have a working and satisfying solution. However, you can take this as a challenge to come up with a better way! – stefan Jul 05 '12 at 01:19
  • See [How do you force a makefile to rebuild a target](http://stackoverflow.com/questions/816370/how-do-you-force-a-makefile-to-rebuild-a-target). – Jesse Good Jul 05 '12 at 01:20
  • @JesseGood Thank you for that link, I did not find this through a search – stefan Jul 05 '12 at 01:22
  • The git source already does this, you might try to take a look at how they do it. I've adapted their system for my own project, which automatically recompiles things when linking against a different flavour of its main library. – araqnid Jul 05 '12 at 09:42
  • @araqnid Can you be a bit more specific? I don't see a connection to git and don't see how this can be easier than what reuben suggested. – stefan Jul 05 '12 at 10:59
  • the build system for the git tool itself (not suggesting using it) does the same thing as you are suggesting- when you make git it can say at the top "compiler flags changed" or suchlike – araqnid Jul 05 '12 at 12:22

4 Answers4

5

As a suggested tweak to Stefan's above response, you can factor out build configuration into a separate file. Instead of somehow force-including this file in your code, you can list the name of this configuration file as a prereq (i.e. to the right of the colon) for all makefile rules you use to build code.

reuben
  • 3,360
  • 23
  • 28
  • as a slightly more insane way: just add "Makefile" as a dependency to every object. There is no need to get this into a separate config file – stefan Jul 05 '12 at 01:33
  • @stefan But you then run the risk that unrelated additions to the makefile force recompilation of everything. This could be extremely painful for large projects. I still like the idea of taking general compiler flags and placing them in a separate config file. – reuben Jul 05 '12 at 01:33
  • 1
    @reuben: depends which risk you prefer, really: the risk that unrelated changes to the makefile recompile everything, or the risk that related changes to the makefile *don't* recompile everything! Normally you're right, of course -- if the person editing the makefile has any doubts at all what needs to rebuild, they can do a `make -B` and pay the price of playing safe. – Steve Jessop Jul 05 '12 at 01:46
0

The basic thing one has to do is making every object depend on a config file.

As a slightly insane solution for c/c++ one can use a file like below which is correct syntax for both makefiles and c/c++.

Instead of having all the compiler flags in the Makefile itself, I create the following file "Makefile_flags":

#undef DUMMY
#define DUMMY /*
PROFILING_FLAGS = -p -g -pg
OPTIMIZATION_FLAGS = -O3
COMPILE_FLAGS = -Wall -Wextra -Wuninitialized -Wmissing-declarations \
                -Wshadow -ftrapv -Wfloat-equal -Wundef -Wpointer-arith \
                -Wcast-align -Wunreachable-code -Wold-style-cast \
                -Wformat=2 -Winit-self -Werror-implicit-function-declaration \
                -Wredundant-decls -Wunsafe-loop-optimizations \
                -pedantic -MD -MP
CPP_STD_FLAGS = -std=c++0x
COMPILE_FLAGS += $(CPP_STD_FLAGS)
COMPILE_FLAGS += $(PROFILING_FLAGS)
COMPILE_FLAGS += $(OPTIMIZATION_FLAGS)
LINKING_FLAGS = $(COMPILE_FLAGS)
#foo */

Now write -include Makefile_flags in your Makefile and #include "Makefile_flags" in every file of your source code you want to have updated (e.g. in every *.c / *.cpp file).

The beauty of this solution: The Makefile uses # as symbol for comments, thus #undef DUMMY, #define DUMMY /* and #foo */ have no effect here. In C/C++ however, /* is used for multiline comments. Thus, the whole non-C-code is ignored by the compiler and the unknown symbol /* is not seen by the Makefile. Additionally, the pre-processor instruction #undef DUMMY takes care of not doing #define DUMMY twice and the #foo statement is inside of the multi-line-comment.

The downside however is, that one must include it in every file.

Make sure that you have the right relative path to your file "Makefile_flags".

stefan
  • 10,215
  • 4
  • 49
  • 90
  • The idea of factoring build configuration into a separate file is interesting. Am I missing something, or would you not be able to simply update the makefile to make its rules depend on this config file. Would that not be sufficient to force a re-evaluation of those rules if and when the config file changes? – reuben Jul 05 '12 at 01:21
  • I do not know what you mean by "simply update the makefile to make its rules depend on this config file". Is that something different than "-include"ing? – stefan Jul 05 '12 at 01:24
  • Could you both include it so that its tweaks took effect, but also list the name of the config file as a prereq (i.e. to the right of the colon) for all makefile rules you use to build code? – reuben Jul 05 '12 at 01:25
  • you're absolutely right, that's brilliant! Then it doesn't even need that fancy commenting anymore :D Would you mind putting that into an answer? – stefan Jul 05 '12 at 01:28
0

The solution to exactly this problem is built into makepp. That automatically detects and takes into account all dependencies, and a changed command is of course one of them.

Daniel
  • 521
  • 1
  • 4
  • 13
0

You could just use a smarter build system, if possible. I use SCons and it has stuff like this built it. It also has nice features like automatically scanning your files for header dependencies so you don't have to manually keep that up to date or run 20 autotools.

David Stone
  • 26,872
  • 14
  • 68
  • 84