title: How to make a makefile for C and C++, with sources in subdirectories
body: <p>I have a project that presently builds in Xcode on OS X.  I'm trying to construct a makefile to allow it to build on other Un*x systems.  I'm a novice at writing makefiles, so I have been cobbling together a makefile from various examples on the web, and perhaps unsurprisingly, I can't get the result to work.  I've looked at other similar questions on SO and gleaned what I can from them, but my situation seems to be a bit different because </p>
  
  <ol>
  <li>I have a large number of source files, so specifying all sources and objects explicitly is not practical, I need to use wildcards</li>
  <li>Some of my sources are in subdirectories, and the same filename can be used in different subdirectories so objects need to be placed by their source files within the file hierarchy to avoid collisions</li>
  <li>I'm building both C and C++ and linking it together at the end</li>
  <li>I want to be able to build two different targets, named "slim" and "eidos", using different subsets of the source files in the directory.  </li>
  </ol>
  
  <p>So please don't mark this as a dup unless the other question really addresses all of these requirements; thanks.  </p>
  
  <p>I would also like to avoid the use of makefile-generation tools, partly because it adds another level of complexity that I don't presently understand, and partly because it seems like overkill since I'm not interested in handling header dependencies and such (see discussion below), and partly because I need maximum portability (I don't want to depend on particular tools being present beyond vanilla <code>make</code>).</p>
  
  <p>The error I'm getting from <code>make -n</code> is a simple one, so my mistake is probably very dumb:</p>
  
  <pre><code>make: *** No rule to make target `gsl/complex/*.c.o', needed by `slim'.  Stop.
  </code></pre>
  
  <p>But it seems to me that <code>*.c.o</code> targets ought to be handled by my <code>%.c.o</code> rule, so I'm puzzled.  My makefile:</p>
  
  <pre><code>SHELL = /bin/sh
  CC = gcc
  CXX = g++
  INCLUDES = -iquote./eidos -iquote./gsl -iquote./gsl/rng -iquote./gsl/randist -iquote./gsl/sys -iquote./gsl/specfunc -iquote./gsl/complex
  CCFLAGS = -O3 -v $(INCLUDES)
  CXXFLAGS = -O3 -v $(INCLUDES) -std=c++11
  
  OUTPUTDIR = ./bin/
  MKDIR = mkdir -p $(OUTPUTDIR)
  
  CSOURCES = ./gsl/*/*.c
  SLIM_CXXSOURCES = ./core/*.cpp ./eidos/*.cpp
  EIDOS_CXXSOURCES = ./eidostool/*.cpp ./eidos/*.cpp
  
  COBJECTS = $(patsubst %.c, %.c.o, $(CSOURCES))
  SLIM_CXXOBJECTS = $(patsubst %.cpp, %.cpp.o, $(SLIM_CXXSOURCES))
  EIDOS_CXXOBJECTS = $(patsubst %.cpp, %.cpp.o, $(EIDOS_CXXSOURCES))
  
  all: slim eidos FORCE
  
  slim: $(COBJECTS) $(SLIM_CXXOBJECTS) FORCE
      $(MKDIR)
      $(CXX) $(COBJECTS) $(SLIM_CXXOBJECTS) -o ./bin/slim
  
  eidos: $(COBJECTS) $(EIDOS_CXXOBJECTS) FORCE
      $(MKDIR)
      $(CXX) $(COBJECTS) $(EIDOS_CXXOBJECTS) -o ./bin/eidos
  
  %.cpp.o : %.cpp
      $(CXX) -c $(CXXFLAGS) -o $@ $&lt;
  
  %.c.o : %.c
      $(CC) -c $(CCFLAGS) -o $@ $&lt;
  
  clean: FORCE
      $(RM) -rf $(OUTPUTDIR)
      $(RM) ./*.o
  
  # Would use .PHONY, but we don't want to depend on GNU make.
  # See http://www.gnu.org/software/make/manual/make.html#Phony-Targets
  # and http://www.gnu.org/software/make/manual/make.html#Force-Targets
  FORCE:
  </code></pre>
  
  <p>I'm not trying to establish per-file header dependencies or anything smart like that.  Instead, I'm just trying to use FORCE to force a full rebuild each time one of the top-level targets (slim, eidos, all) is built.  This is because I don't expect people to use this makefile during development; all development is done on OS X in Xcode.  So it doesn't need to be minimal/efficient, it just needs to work reliably to produce a final product.  I'm not sure that I'm using FORCE correctly, though.</p>
  
  <p>I also have a couple of side questions.  </p>
  
  <ol>
  <li>I took the <code>$&lt;</code> endings for the two compilation commands from example makefiles on the web, but I don't know what they do.  What's going on there?  It looks like a redirection, but it's not a redirection command I'm familiar with, and of course Google is useless for searching for symbolic things like this. </li>
  <li>The <code>patsubst</code> business is a bit tricky, and I don't know how to tell whether it's working or not.  I tried <code>make -np</code> to print out <code>make</code>'s internal info, but it seems to show variables with their original definitions, not with their resolved definitions, so I can't tell what the final value is that <code>make</code> will actually use for my variables.  How can I debug this?  And is <code>patsubst</code> a standard part of <code>make</code>?  Is there a better way to do what I'm trying to do there?</li>
  </ol>
  
  <p>Thanks.  Sorry for the hectic multi-part question.  By the way, all I'm really trying to do is convert the previously existing makefile to build source files individually, producing .o object files, and then link at the end.  The previously existing makefile built everything in a single call to g++, which is causing problems for some users because of excessive memory usage and build time.  Here's the old Makefile:</p>
  
  <pre><code>SHELL = /bin/sh
  CC = g++
  CFLAGS = -O3 -Wno-deprecated-register
  INCLUDES = -iquote./eidos -iquote./gsl -iquote./gsl/rng -iquote./gsl/randist -iquote./gsl/sys -iquote./gsl/specfunc -iquote./gsl/complex
  ALL_CFLAGS = $(CFLAGS) $(INCLUDES) -std=c++11
  
  all: slim eidos FORCE
  
  slim: FORCE
      mkdir -p ./bin
      $(CC) $(ALL_CFLAGS) ./core/*.cpp ./eidos/*.cpp ./gsl/*/*.c -o ./bin/slim
  
  eidos: FORCE
      mkdir -p ./bin
      $(CC) $(ALL_CFLAGS) ./eidostool/*.cpp ./eidos/*.cpp ./gsl/*/*.c -o ./bin/eidos
  
  clean: FORCE
      rm -f ./bin/slim
      rm -f ./bin/eidos
  
  # Would use .PHONY, but we don't want to depend on GNU make.
  # See http://www.gnu.org/software/make/manual/make.html#Phony-Targets
  # and http://www.gnu.org/software/make/manual/make.html#Force-Targets
  FORCE:
  </code></pre>
  
  <p>That works fine, apart from the aforementioned issue of being slow and using a ton of memory.</p>