29

I have a makefile that takes options at the command line

make OPTION_1=1

Based on the value it will add additional compiler definitions to a subset of objects.

ifeq ($(OPTION_1), 1)
CC_FLAGS += -DOPTION_1_ON
endif

The change in the definition affects the included header file content - a stub or an implementation is exposed to the object files.

How can I get make to rebuild the files 'affected' by this option changing?

Oliver
  • 2,175
  • 3
  • 24
  • 31

1 Answers1

48

I use a file to remember the last value of such options, like this:

.PHONY: force
compiler_flags: force
    echo '$(CC_FLAGS)' | cmp -s - $@ || echo '$(CC_FLAGS)' > $@

The cmp || echo bit means the file compiler_flags is only touched when the setting changes, so now you can write something like

$(OBJECTS): compiler_flags

to cause a rebuild of $(OBJECTS) whenever the compiler flags change. The rule for compiler_flags will be executed every time you run make, but a rebuild of $(OBJECTS) will be triggered only if the compiler_flags file was actually modified.

slowdog
  • 6,076
  • 2
  • 27
  • 30
  • Thanks for the example. Shame it doesn't appear possible to do this without a temp file. – Oliver Jul 13 '10 at 22:04
  • 1
    Edited to avoid creating `compiler_flags.tmp`, makes it look a little tidier. I suspect that's not what you meant, though. There's no way around creating *some* file to remember the setting, since make has no other way to preserve state across multiple invocations. – slowdog Jul 14 '10 at 15:01
  • 1
    This is more than a tad inefficient if your build gets big. It implies a shell invocation and a file read even for an up-to-date build. In these circumstances, encode the compiler flags in the _filename_. – bobbogo Jan 09 '14 at 23:15
  • If you can come up with a short description of the aspects of compile flags that are likely to change, then I agree. For a general solution though, you'd likely run afoul of operating system limits on file path lengths if you put the entire command line into the filename. It also would not make for very readable build log output. – slowdog Jan 31 '14 at 13:34
  • 1
    You could compute a hash digest of the command line, and use that for a suffix on the filename. – cbehanna Jan 02 '15 at 23:18
  • @bobbogo Using the filename won't help you much if you build with flags set A, then change the sources for object X and build with flags set B, then change sources for object Y and rebuild with flags set A again. You won't rebuild X since the flags-file dependency is still older than the sources for X. Unless you touch it, in which case you're forcing full rebuilds each time anyway. – Craig Ringer Apr 18 '17 at 06:35
  • 1
    @bobbogo Can you explain how can this become inefficient? I believe the rule is executed once per `make`, so unless you have an automatic script to execute `make` many times, the overhead should be negligible. – Imperishable Night Oct 14 '17 at 06:37
  • @ImperishableNight I did mention _big builds_. Imagine a recursive build (bad enough) with a load of sub-dirs. IMHO one of the most important metrics in a build is the _time to do nothing_. If I hit _make_ when the build is already up-to-date, I don't want to wait 30 seconds! – bobbogo Oct 16 '17 at 10:34
  • @CraigRinger It's not about avoiding the full rebuild (like you said, you need to do that), it's about avoiding command execution when the build is already up-to-date – bobbogo Oct 16 '17 at 10:37