title: How can I make a target "private" in GNU make for internal use only? OR: how to best enforce target-specific variable-values?
body: <p>I have some ancillary targets in a makefile that I want to restrict for internal or "private" use (only) inside the makefile.  That is, I want to be able to specify these targets as dependencies from within the makefile, but I want to prevent the target from being specified as a build goal from the command line.  Somewhat analogous to a <code>private</code> function from OOP: the target is harmful (or simply doesn't make sense) to build separately.</p>
  
  <p>I wish there were a special-target <code>.HIDDEN</code> or <code>.PRIVATE</code> or something that did this, akin to what <code>.PHONY</code> does for non-file targets, but I don't think this exists.  The <code>private</code> keyword is only for variables.</p>
  
  <p><strong>What is a good/general/elegant way to protect a target for internal/private use only?</strong></p>
  
  <p>The best workaround that I could come up with is to check <code>$(MAKECMDGOALS)</code> for "unacceptable" targets, then error-out if specified; this seems inelegant. I'm sure the makefile could be rewritten to avoid this situation -- perhaps a superior solution -- but that's not practical here.</p>
  
  <hr>
  
  <p>Below the cut-line... here's a contrived example for illustration.</p>
  
  <p>Though I'm looking for a general solution, one example of targets that are harmful as individual/primary goal is with inheriting of target-specific variable values:</p>
  
  <pre><code>override CFLAGS += -Wall
  all : debug
  %.o : %.c
      $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $&lt;
  debug   : CFLAGS += -g3 -O0
  release : CFLAGS +=     -O3
  debug   : CPPFLAGS += -DDEBUG
  release : CPPFLAGS += -DRELEASE
  debug release : foo.o bar.o main.o
      $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
  clean:
      -rm -f *.o debug release
  .PHONY: all clean
  </code></pre>
  
  <p>Implicit rule duplicated (unnecessary) for illustration. With the goal of <code>debug</code> or <code>release</code>, <code>foo.o</code> and others will inherit respective <code>CFLAGS</code> and <code>CPPFLAGS</code> -- If one does <code>make clean debug</code> all objects will be consistent. But for example if someone builds <code>foo.o</code> separately, it will fail to inherit the appropriate flags; e.g., <code>make clean foo.o debug</code> you'll get <code>foo.o</code> built with default <code>CFLAGS</code>; then it doesn't need to be updated when building <code>debug</code>, so it will be linked with other objects with different optimizations or different macro settings.  It will probably work in this case, but it's not what was intended. Marking <code>foo.o</code>, etc. as illegal goals would prevent this.</p>
  
  <hr>
  
  <p>EDIT:</p>
  
  <p>It's very clear that my example (above) was not a good choice for my more-general question: hiding targets was not the best way to fix <em>an issue with my example</em>.  Here's a modified example that illustrates the modified question "How to enforce target-specific values?" -- it builds on commentary from @Michael, @Beta, @Ross below, and allows posing and answering this more limited scenario.</p>
  
  <p>As described in previous responses below, it's a much better idea in this case to create objects that have different build flags in separate locations. e.g., </p>
  
  <pre><code>bin_debug/%.o   : %.c
      $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $&lt;
  bin_release/%.o : %.c
      $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $&lt;
  OBJS = foo.o bar.o main.o # or $(SRCS:.o=.c)
  DEBUG_OBJS   = $(addprefix bin_debug/,$OBJS)
  RELEASE_OBJS = $(addprefix bin_release/,$OBJS)
  debug   : $(DEBUG_OBJS)
  release : $(RELEASE_OBJS)
  debug release :
      $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
  </code></pre>
  
  <p>Pattern rule duplicated because I think it has to be (multiple "pattern targets" (<code>%</code>) convince <code>make</code> all targets are built at once with one recipe; see SO questions <a href="https://stackoverflow.com/q/11441084/3562032">this</a> and <a href="https://stackoverflow.com/q/2973445/3562032">this</a>).</p>
  
  <p>So now, add in target-specific flags:</p>
  
  <pre><code>debug   : CPPFLAGS += -DDEBUG
  release : CPPFLAGS += -DRELEASE
  </code></pre>
  
  <p>But this still suffers:</p>
  
  <pre><code>make bin_debug/foo.o
  </code></pre>
  
  <p>will not get the <code>CPPFLAGS</code> from <code>debug</code>.  I've accepted @Michael's answer below as it got me thinking about the problem in a more helpful way, but also answered some of my own rhetorical questions below.</p>